home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-10-24 | 6.1 MB | 135,132 lines | [TEXT/MPS ] |
Text Truncated. Only the first 1MB is shown below. Download the file for the complete contents.
- æKY CopyrightNotice
- æC Copyright Apple Computer, Inc. 1985-1990, All rights reserved.
- 411 - Inside Macintosh Help - MPW 3.2 Beta Release.
- Monday, October 22, 1990 9:00:00 AM
-
- Information source: SpInsideMacintosh 1.0 HyperCard stack.
- Pegasus 1.2.5 Hypercard Stack IM Vol VI
- æKY Help
- InsideMacintoshHelp
- æC
- AboutInsideMacintoshHelp Preface UserInterfaceGuidelines
- IntroductiontoSystem7.0 RoadMap WorldwideSoftwareOverview
-
-
- AliasManager HelpManager ScriptManager
- AppleTalkManager ListManager SCSIManager
- ColorManager MemoryManager ShutdownManager
- ControlManager MenuManager SlotManager
- DatabaseAccessManager NotificationManager SoundManager
- DeferredTaskManager OSEventManager StartManager
- DeskManager PackageManager TimeManager
- DeviceManager PaletteManager ToolboxEventManager
- DialogManager PowerManager VerticalRetraceManager
- EditionManager PrintingManager WindowManager
- EventManager ProcessManagement
- FileManager QuickDraw
- FontManager ResourceManager
- GraphicsDevicesManager ScrapManager
-
-
- AppleDesktopBus FloatingPointPackage SoundDriver
- BinaryDecimalConversion GraphicsOverView StandardFile
- ColorPickerPackage InternationalUtilities SystemErrorHandler
- ColorQuickDraw MacintoshHardware SystemResourceFile
- CompatibilityGuidelines MemoryManagement TextEdit
- ControlPanels OSUtilities ToolboxUtilities
- DiskDriver PPCToolbox UsingAssemblyLanguage
- DiskInitialization SegmentLoader
- FinderInterface SerialDrivers
-
-
- A.ResultCodes C.SystemTraps SystemErrors
- B.MovesMemory D.GlobalVariables Glossary
-
-
-
-
- æKY AboutInsideMacintoshHelp
- æC
- ------------------------------------------------------------------------------
- Version 1.0 Beta:
-
- Volume VI chapters have been added to this version which contain information
- about System 7.0, new managers and changes to previous ones.
-
- New manager chapters are:
- AppleTalk Manager
- DatabaseAccess Manager
- Edition Manager
- Event Manager
- GraphicDevices Manager (Replaces the Graphic Devices chapter in Volume V)
- Help Manager
- Memory Management
- Power Manager
- PPC Toolbox
- Process Management
-
- Changed chapters are:
- Alias Manager
- Color Picker Package
- Color Quikdraw
- Control Panels
- File Manager
- FinderInterface
- Font Manager
- Notification Manager
- Palette Manager
- Resource Manager
- Slot Manager
- Sound Manager
- TextEdit
- Time Manager
-
- New/changed documentation chapters are:
- Compatibility Guidelines
- Graphics Overview
- Introduction to System 7.0
- Preface
- UserInterface Guidelines VI
- Worldwide Software Overview
-
- ------------------------------------------------------------------------------
- Version 1.0 Alpha:
-
- InsideMacintoshHelp file provides on-line documentation for the 411 project.
- This version contains all the chapters of InsideMacintosh Volumes I - V.
- æKY AliasManager
- æC
- _______________________________________________________________________________
-
- ALIAS MANAGER
- _______________________________________________________________________________
-
- About…the…Alias…Chapter
- About…the…Alias…Manager
- About…Alias…Records
- Strategies…for…Resolving…Alias…Records
- Fast…Search
- Slow…Search
- Using…the…Alias…Manager
- Creating…Alias…Records
- Resolving…Alias…Records
- ResolveAlias
- SelectAlias
- MatchAlias
- Reading…Alias…Records
- Maintaining…Alias…Records
- Storing…and…Retrieving…Alias…Records
- Alias…Manager…Routines
- Creating…and…Updating…Alias…Records
- Resolving…and…Reading…Records
- Summary…of…the…Alias…Manager
- Alias…Constants
- Alias…Data…Types
- Alias…Routines
- Alias…Result…Codes
- Assembly-Language…Information…for…Alias
- _______________________________________________________________________________
-
-
-
- æKY About…the…Alias…Chapter
- æC »ABOUT THIS CHAPTER Alias Manager
- _______________________________________________________________________________
-
- This chapter describes how your application can use the Alias Manager to
- establish and resolve alias records, which are data structures that describe a
- file, folder, or volume.
-
- You create an alias record to take a fingerprint of an object, usually a file,
- that you might need to locate again later. If you store the alias record,
- instead of a conventional file specification such as name and parent directory
- ID, you can later use the Alias Manager’s algorithms for finding files that have
- been moved, renamed, copied, or restored from backup.
-
- Note: The Alias Manager is a utility for exploiting alias records. It does not
-
- directly manipulate desktop aliases, which are created and managed by the
-
- Finder. (The Finder Interface chapter describes desktop aliases.)
-
- The Alias Manager is available only in system software version 7.0. Call the
- Gestalt function, described in the Compatibility Guidelines chapter of this
- volume, to determine whether the Alias Manager is present.
-
- Read this chapter if you want your application to create and resolve alias
- records. You might use an alias record, for example, to identify a customized
- dictionary from within a text document. When the user runs a spelling checker on
- the document, your application can ask the Alias Manager to resolve the record
- to find the correct dictionary.
-
- To use this chapter, you should be familiar with the File Manager’s conventions
- for identifying files, folders, and volumes, as described in the File Manager
- chapters in volume IV and this volume.
-
- _______________________________________________________________________________
-
- æKY About…the…Alias…Manager
- æC »ABOUT THE ALIAS MANAGER Alias Manager
- _______________________________________________________________________________
-
- The Alias Manager creates and resolves alias records. The next section, “About
- Alias Records,” describes how you can use alias records.
-
- In general, you should use the Alias Manager whenever you find yourself storing
- specific file or directory information such as full pathname or filename and
- parent directory ID. The Alias Manager stores this information and more in the
- alias record, and it also provides a set of search strategies for resolving the
- record later. The search strategies are described in “Resolving Alias Records,”
- later in this chapter.
-
- You can use the Alias Manager to
- • create and resolve alias records
- • get information from and update alias records
-
- The Alias Manager can track files and folders across volumes. If the target of
- an alias record is on an unmounted AppleShare® volume, the Alias Manager can
- automatically initiate the mounting when it resolves the alias. If the target
- object is on an unmounted ejectable disk, the Alias Manager can prompt the user
- to insert the disk.
-
- When the Alias Manager creates an alias record, it fills in the record and
- returns a handle to it. Your application must store and retrieve the records on
- disk if necessary. Your application must also supply strategies for handling
- various alias-resolution problems, described in “Resolving Alias Records.”
-
- To help you understand and use the Alias Manager, this chapter provides
- • an overview of alias records
- • a description of how the Alias Manager resolves alias records
- • specific techniques for using the Alias Manager in your application
- _______________________________________________________________________________
-
- æKY About…Alias…Records
- æC »ABOUT ALIAS RECORDS Alias Manager
- _______________________________________________________________________________
-
- An alias record is a data structure that describes a file, folder, or volume.
- The record contains a collection of information about its target, including its
- name and file ID, creation date, parent directory name and ID, and volume name
- and creation date.
-
- By storing alias records, you can allow your users to create robust connections
- between files—--that is, connections that can survive the moving or renaming of
- one or both files. The Finder™ in system software version 7.0 stores an alias
- record when the user creates a desktop alias object. The Edition Manager uses
- alias records to implement data-sharing among separate documents. (The Finder
- Interface and Edition Manager chapters in this volume describe those features in
- detail. The section “Using the Alias Manager,” later in this chapter, describes
- how the Finder and the Edition Manager call the Alias Manager.)
-
- The alias record itself contains two kinds of information: public information
- available to your application and private information used by the Alias Manager.
-
- TYPE
- AliasHandle = ^AliasPtr;
- AliasPtr = ^AliasRecord;
- AliasRecord =
- RECORD
- userType: OSType; /* application’s signature */
- aliasSize: Integer /* record size when created */
- {variable-length private data}
- END;
-
- Your application can use the userType field to store its own signature or any
- other data that fits in four bytes. When the Alias Manager fills in an alias
- record, it stores four spaces (0x20202020) in that field.
-
- The Alias Manager stores the size of the record when it was created in the
- aliasSize field. Knowing the starting size allows your application to store and
- retrieve data of its own at the end of the record. First, expand the size of the
- record with the Memory Manager, described in Volume II. You can then find the
- starting address of your own data in the record by adding the record’s starting
- address to its original length, as reported in the aliasSize field.
-
- The private Alias Manager data includes a collection of file, directory, and
- volume names and their creation dates; file and directory IDs; a full pathname,
- including the volume name; and, if applicable, AppleShare information for use in
- resolving the alias record.
-
- When you create an alias record, you have the option of recording a relative
- path, that is, the path to the target object from another file or folder on the
- same disk. The beginning point of a relative path is called the fromFile. To
- record relative path, the Alias Manager saves the distances from the target and
- the fromFile to the common parent, that is, the lowest-level directory that
- appears in the pathnames of both. The Alias Manager can later use those
- distances in conjunction with the absolute pathname to conduct a relative
- search.
-
- Suppose, for example, that you are writing a word-processing application that
- allows the user to build a customized, supplemental dictionary for each
- document. You create the dictionary as a separate document in the same folder as
- the document it serves, as Figure 24-1 shows.
-
- ø 24.1 Recording of Relative Path
-
- When resolving the alias record using relative path, the Alias Manager starts at
- the directory the specified distance above the fromFile, the directory named
- Sample in the example above. The Alias Manager then constructs a pathname by
- using one field of the absolute pathname for each step from the target to the
- common parent. In this example, the distance is one, so the pathname contains
- only the name of the target document, Dictionary.
-
- In some circumstances, a relative search identifies the correct target when an
- absolute search could not. For example, suppose the user of your word-processing
- application creates a working copy of a document and dictionary by copying the
- entire folder Sample to another disk. The user later updates the original
- document and dictionary by copying the folder from the working disk. All of the
- underlying file and folder identifications change, but the filenames and
- relative path remain the same. When the user later runs the spelling checker on
- the document, a relative-path search finds the target dictionary.
-
- The Alias Manager accepts and returns file specifications only in the form of
- file system specification records (FSSpec records), described in the File
- Manager chapter of this volume. The FSSpec record represents the simlest
- complete description of a file system object. It contains a volume reference
- number, a parent directory ID, and a name.
-
- _______________________________________________________________________________
-
- æKY Strategies…for…Resolving…Alias…Records
- æC »STRATEGIES FOR RESOLVING ALIAS RECORDS Alias Manager
- _______________________________________________________________________________
-
- The Alias Manager provides three alias-resolution functions:
-
- • The high-level function ResolveAlias performs a fast search for a single
- target. If the target resides on an unmounted volume, ResolveAlias
- attempts to mount the volume automatically. If it finds no match for the
- alias record, ResolveAlias simply returns an error code.
-
- • The high-level function SelectAlias can identify more than one possible
- target. If it identifies either no targets or more than one possible
- target, it displays a dialog box, through which the user can direct the
- search. SelectAlias starts with a fast search and can perform a slow
- search at the user’s request. (Fast and slow searches are described
- below.) If the target resides on an unmounted volume, SelectAlias
- attempts to mount the volume automatically.
-
- • The low-level function MatchAlias accepts a set of input rules to control
- the search. MatchAlias can perform either a fast or a slow search. It can
- identify and return multiple possible targets. Your program must process
- the results.
-
- The following sections describe the fast- and slow-search algorithms the Alias
- Manager uses to resolve alias records. For information on using the functions,
- see “Using the Alias Manager” and “Alias Manager Routines” later in this
- chapter.
-
- _______________________________________________________________________________
-
- æKY Fast…Search
- æC »Fast Search Alias Manager
- _______________________________________________________________________________
-
- The fast-search algorithm is designed to find the most likely match for an alias
- record first. This strategy meets the needs of the ResolveAlias function, which
- exits as soon as it finds one match. The fast-search algorithm can, however,
- identify more than one possible target for presentation to the user through the
- SelectAlias function.
-
- The first step in the search is to identify the volume on which the target
- resides, using the volume’s name, creation date (which acts almost as a unique
- identifier for a volume), and volume type (for example, a hard disk, a 3.5-inch
- disk, or an AppleShare volume).
-
- The Alias Manager first looks for a volume by both name and creation date. The
- search succeeds if the volume is mounted and if its name and creation date have
- not changed since the record was created. If the target is on an unmounted
- AppleShare volume, the Alias Manager attempts to mount the volume. If the target
- is on an unmounted ejectable disk, the Alias Manager presents the switch-disk
- dialog box, illustrated in Figure 24-2.
-
- ø 24.2 Switch-Disk Dialog Box
-
- If the target volume is not found by name and creation date, the Alias Manager
- attempts to match by creation date only. This step locates volumes that have
- been renamed. Finally, the Alias Manager attempts to match by volume name only.
-
- If none of these strategies results in a volume match, the Alias Manager returns
- nvsErr.
-
- Once the target volume is identified, fast search looks for the actual target,
- first by file ID (if the target is a file) or directory ID (if the target is a
- volume or directory). (File IDs are described in the File Manager chapter of
- this volume.) Even if a file has been renamed or moved on a volume, the File
- Manager can find it quickly through its file ID.
-
- If the search by file ID or directory ID fails, fast search looks for the target
- by name in the original parent directory. This search locates the target if its
- file or directory ID has changed but it still exists by the same name in the
- parent directory (for example, if the target was restored from backup). Fast
- search compares file numbers on files found by name in the correct parent
- directory. If the file numbers do not match, the file is treated as a possible
- match, that is, it is put on the list of candidates and the search continues. If
- the target is not found by name in the parent directory, fast search looks for a
- file by file number in the parent directory.
-
- If the search by file ID or directory ID fails, and if fast search cannot find
- the original parent directory, it searches for the target by full pathname. This
- search finds the target if it resides in the same location on the disk but the
- directory ID of its parent directory has changed (for example, if the entire
- parent directory was backed up and restored).
-
- If the full pathname fails, fast search attempts to find the file by tracing
- partial pathnames up through all parent folders, using parent directory IDs
- instead of folder names. For example, consider this full pathname:
-
- MyDisk:MyReports:January:Sales Report
-
- If the search by full pathname fails, fast search first looks for the partial
- pathname Sales Report in the directory MyDisk:MyReports:January. If that search
- fails, it looks for January:Sales Report in the directory MyDisk:MyReports, and
- so on.
-
- If the search by absolute pathname fails, and if your application requests a
- relative search, fast search performs a relative search. (For a description of
- relative path, see “About Alias Records” earlier in this chapter.) The search
- succeeds if the relative path is the same as when the record was created and if
- the names of the objects have not changed.
-
- _______________________________________________________________________________
-
- æKY Slow…Search
- æC »Slow Search Alias Manager
- _______________________________________________________________________________
-
- The slow-search algorithm uses the same strategy as fast search for identifying
- the volume.
-
- Once the volume is identified, slow search calls the File Manager function
- PBCatSearch, searching for objects with a matching creation date, creator, and
- type. (See the File Manager chapter for a description of PBCatSearch.) It
- searches the entire volume.
-
- PBCatSearch is available only on Hierarchical File System (HFS) volumes, not on
- Macintosh File System (MFS) volumes. (See the File Manager chapter of this
- volume for a description of the two file systems.) PBCatSearch is also available
- only on systems running version 7.0 and later. When searching an MFS volume or a
- volume on a file server running older system software, slow search performs a
- recursive search of the entire volume, searching for objects with matching
- creation date, type, creator, or file number.
-
- _______________________________________________________________________________
-
- æKY Using…the…Alias…Manager
- æC »USING THE ALIAS MANAGER Alias Manager
- _______________________________________________________________________________
-
- You use the Alias Manager primarily to create and resolve alias records. You can
- also use it to look at and update alias records.
-
- The Alias Manager creates an alias record in memory and provides you with a
- handle to the record. Your application can store the records on disk as
- resources of type 'alis' (see “Creating and Updating Alias Records”). When you
- no longer need the record in memory, call the DisposHandle procedure, described
- in the Memory Manager chapter of Volume II, to free the memory occupied by the
- record.
-
- All Alias Manager routines accept and return file specifications only in the
- form of FSSpec records, which contain a volume reference number, a parent
- directory ID, and a target name. Use the File Manager function MakeFSSpec to
- convert other forms of file identification, such as pathname, into a canonical
- file specification (see the File Manager chapter in this volume for a
- description of file identification conventions).
-
- For more detailed descriptions of the functions described in this section, see
- “Alias Manager Routines” later in this chapter.
-
- _______________________________________________________________________________
-
- æKY Creating…Alias…Records
- æC »Creating Alias Records Alias Manager
- _______________________________________________________________________________
-
- You create a new alias record by calling the NewAlias function. NewAlias fills
- in the record and provides a handle to it. NewAlias always records a collection
- of information about the target, including the full pathname. You can request
- that it store relative path information as well by supplying a starting point
- for a relative search.
-
- Call NewAlias when you want to store a file description for later use. For
- example, suppose you were writing a word-processing application that allows the
- user to customize a dictionary for use with a single text file. Your application
- stores the custom data in a separate file in the same folder as the document. As
- soon as you create the dictionary file, you call NewAlias to create an alias
- record for that file, including path information relative to the user’s text
- document:
-
- MyErr := NewAlias(textFilePtr, targetPtr, myAliasHdl);
-
- The parameter textFilePtr is a pointer to a FSSpec record that identifies the
- starting point for the relative search, in this case the user’s text file. If
- you do not want relative path information recorded, pass a value of NIL in the
- first parameter.
-
- The parameter targetPtr is a pointer to a FSSpec record that identifies the
- target file, in this example the dictionary file.
-
- The parameter myAliasHdl a variable in which the Alias Manager returns a handle
- to the target description.
-
- _______________________________________________________________________________
-
- æKY Resolving…Alias…Records
- æC »Resolving Alias Records Alias Manager
- _______________________________________________________________________________
-
- The Alias Manager provides three alias-resolution functions:
-
- • ResolveAlias, which simply searches for one target and exits if it fails
-
- • SelectAlias, which searches for all plausible targets and displays a
- dialog box to the user if it finds either more than one target or no
- targets
-
- • MatchAlias, which returns one or more targets
-
- ResolveAlias and SelectAlias are both high-level functions, which call the
- low-level function MatchAlias. The sections below describe the three functions
- in detail. The section “Strategies for Resolving Alias Records,” earlier in this
- chapter, describes the underlying search strategies used by the alias-resolution
- functions.
-
- In general, when you want to identify only the single most likely target of an
- alias record, you call ResolveAlias. When you want the user to guide the
- resolution of any ambiguous records, you call SelectAlias. When you want your
- program to control the search or branch depending on the outcome, you call
- MatchAlias.
-
- For example, the Finder stores a single alias record for each alias object that
- appears on the desktop. When the user opens an alias from the Finder, the Finder
- identifies the real object to be opened by resolving the alias record before it
- starts up the appropriate application. The Finder calls the ResolveAlias
- function, which either finds the target or exits.
-
- The Edition Manager follows a more complicated strategy, designed to shield the
- user from dialog boxes until they are necessary. Applications can use the
- Edition Manager to allow users to incorporate information from one document into
- another. When the user inserts shared data into a document, the Edition Manager
- stores an alias record that points to the edition, that is, the file that
- contains the shared data. Figure 24-3 illustrates how an alias record in a user
- document points to an edition.
-
- ø 24.3 How the Edition Manager Uses an Alias Record
-
- When the user opens a document that includes one or more sections of shared
- data, the Edition Manager first checks to see if any of the shared data is out
- of date. It then makes a quick attempt to resolve the alias records for all
- sections that need to be updated. It calls MatchAlias for each record,
- requesting a fast search with automatic mounting suppressed and a maximum of two
- matches. If MatchAlias finds only one match for a record, the Edition Manager
- accepts that candidate as the correct target. If MatchAlias finds no matches or
- two matches, the Edition Manager simply tags that record as unresolved. When the
- user tries to display or print a portion of the document that contains an
- unresolved record, the Edition Manager calls SelectAlias, which either finder
- the target or prompts the user to direct the search for the correct target. This
- strategy provides automatic resolution of unambiguous alias records, allows the
- user to resolve ambiguities, and delays alias-resolution dialogs until they are
- really necessary.
-
- _______________________________________________________________________________
-
- æKY ResolveAlias
- æC »ResolveAlias Alias Manager
- _______________________________________________________________________________
-
- In the simplest case, you can call the ResolveAlias function to resolve an alias
- record. ResolveAlias performs a fast search (described in “Strategies for
- Resolving Alias Records”) and exits after it identifies one target.
-
- ResolveAlias compares some key information about the identified target with the
- information stored in the alias record. If any of the information is different,
- ResolveAlias automatically updates the record.
-
- In the dictionary example, illustrated in Figure 24-1, above, the application
- calls ResolveAlias when the user runs the spelling-checker on an application
- with a customized dictionary.
-
- MyErr := ResolveAlias(textFilePtr, myAliasHdl, targetPtr, updateFlag);
-
- The parameter textFilePtr is a pointer to a FSSpec record that identifies the
- starting point for the relative search, in this case the user’s text file. If
- you do not want relative path information used in the search, pass a value of
- NIL in the first parameter.
-
- The parameter myAliasHdl points to the alias record to be resolved. In this
- example, the alias record describes the dictionary file.
-
- The parameter targetPtr is a is a pointer to the FSSpec record where the Alias
- Manager will place the results of its search. After ResolveAlias completes, the
- record pointed to by targetPtr contains the specification for the dictionary
- file.
-
- The ResolveAlias function uses the updateFlag parameter to report whether or not
- it updated the alias record. After ResolveAlias completes, updateFlag is TRUE if
- the record was updated and FALSE if it was not.
-
- _______________________________________________________________________________
-
- æKY SelectAlias
- æC »SelectAlias Alias Manager
- _______________________________________________________________________________
-
- If you want to let the user handle any ambiguities in the resolution, you can
- call the SelectAlias function to resolve an alias.
-
- The SelectAlias function always performs a fast search first. If the search
- identifies only one target, it behaves exactly like ResolveAlias. If the search
- identifies no targets or more than one possible target, the Alias Manager
- presents a dialog box like the one in Figure 24-4.
-
- ø 24.4 SelectAlias dialog box
-
- In this example, the user moved the original target file, Sales Report, to a
- different folder. Later, the user copied the file back into its original parent
- folder and renamed the original file, now in a different folder, Old Sales
- Report. The Sales Report file now appears in the correct parent directory with
- the correct name but a different file ID. The file Old Sales Report appears in a
- different parent directory with a different name but with the original file ID.
- The fast-search algorithm identifies both files as possible targets.
-
- The first field in the dialog box informs the user of the ambiguity. The message
- is fixed except for the name of the target and the type description, which is
- the word immediately before the target name (Edition in this example). You can
- control the type description through the fileTypeName parameter in the
- SelectAlias function. If you pass an empty string in this parameter, the Alias
- Manager substitutes the word document or folder, depending on what kind of
- object the alias describes. The name of the target is the original filename
- stored in the alias record.
-
- The left scroll list, labeled “Name:”, shows the names of all possible alias
- matches. The first entry is highlighted when the dialog box first appears.
-
- The right scroll list, labeled “Location:”, displays the full path of whatever
- entry is highlighted in the Name column. Entries in this list are not
- selectable.
-
- The Select button accepts the highlighted entry as the target of the alias
- record. When the user clicks Select, SelectAlias removes the dialog box and
- places the highlighted entry in the target parameter. Pressing the Enter or
- Return key or double-clicking an entry in the name list has the same effect as
- clicking Select.
-
- The Cancel button cancels the entire selection process. When the user clicks
- Cancel, SelectAlias removes the dialog box and returns userCanceledErr. Pressing
- the Esc (Escape) key or Command-period has the same effect as clicking Cancel.
-
- The Try Harder button triggers an asynchronous slow search of all mounted
- volumes, beginning, if possible, with the volume on which the target resided
- when the alias record was last updated. If the slow search identifies additional
- possible matches, the Alias Manager adds them to the name list. If the slow
- search takes more than three seconds in real time, the Alias Manager presents a
- dialog box that allows the user to cancel the search in progress. Once the Alias
- Manager has completed the slow search, it dims the Try Harder button.
-
- The Another One button lets the user override the entire selection process. The
- Alias Manager presents a dialog box much like the Standard File Package dialog
- box, which allows the user to select any file or folder on the system. Clicking
- OK accepts the highlighted object as the target of the search. While this dialog
- box is on the screen, clicking Cancel returns the user to the SelectAlias dialog
- box.
-
- In the dictionary example described above, the application could call
- SelectAlias instead of ResolveAlias so that the user can help locate the correct
- dictionary if a fast search fails to find it.
-
- MyErr := SelectAlias(textFilePtr, typeStr, NIL, myAliasHdl, targetPtr,
- updateFlag, NIL, NIL);
-
- The parameter textFilePtr is a pointer to a FSSpec record that identifies the
- starting point for the relative search, in this case the user’s text file. If
- you do not want relative path information used in the search, pass a value of
- NIL in the first parameter.
-
- The parameter typeStr points to a string containing the word Dictionary. When
- SelectAlias displays its dialog box, it uses this string to remind the user that
- the target is a dictionary file.
-
- The first NIL parameter tells SelectAlias that the application is not supplying
- a filter function to process the results of the search.
-
- The parameter myAliasHdl points to the alias record to be resolved. In this
- example, the alias record describes the dictionary file.
-
- The parameter targetPtr is a is a pointer to the FSSpec record where the Alias
- Manager will place the results of its search. After SelectAlias completes, the
- record pointed to by targetPtr contains the specification for the dictionary
- file.
-
- The SelectAlias function uses the updateFlag parameter to report whether or not
- it updated the alias record. After SelectAlias completes, updateFlag is TRUE if
- the record was updated and FALSE if it was not.
-
- The second NIL parameter controls the filtering of events by the ModalDialog
- procedure while the SelectAlias dialog box is on the screen. A value of NIL
- means that your application does no special filtering. (SelectAlias calls
- ModalDialog when it displays the SelectAlias dialog box. For a description of
- the ModalDialog procedure, see the Dialog Manager chapter of Volume I.) Because
- this example does not provide a custom filter function, it does not need to pass
- any data of its own, and it sets the final parameter to NIL.
-
- _______________________________________________________________________________
-
- æKY MatchAlias
- æC »MatchAlias Alias Manager
- _______________________________________________________________________________
-
- The MatchAlias function is a low-level routine that gives your program control
- over the searching algorithm.
-
- You can control the search by setting flags in the rulesMask parameter. The
- flags let you specify whether to attempt an automatic mounting of unmounted
- volumes; whether to search on more than one volume; and whether to perform a
- fast search, a slow search, or both. (For details about the rulesMask parameter,
- see “Alias Manager Routines” later in this chapter.) You can also specify a
- maximum number of candidates to be identified.
-
- MatchAlias returns all candidates that it identifies in an array of FSSpec
- records.
-
- You can use MatchAlias to perform a preliminary search for a target, branching
- to different routines depending on the outcome. The Edition Manager calls
- MatchAlias, as described in the introduction to this section, “Resolving Alias
- Records.”
- _______________________________________________________________________________
-
- æKY Reading…Alias…Records
- æC »Reading Alias Records Alias Manager
- _______________________________________________________________________________
-
- To retrieve information from an alias record without actually resolving the
- record, call the GetAliasInfo function. You can use GetAliasInfo to retrieve the
- name of the target, the names of its parent directories, the name of its volume,
- or, in the case of an AppleShare volume, the zone or server name.
-
- _______________________________________________________________________________
-
- æKY Maintaining…Alias…Records
- æC »Maintaining Alias Records Alias Manager
- _______________________________________________________________________________
-
- To update an alias record, call the UpdateAlias function. You can use
- UpdateAlias any time you know that the target of an alias record has been
- renamed or otherwise changed.
-
- You are most likely to call UpdateAlias after a call to the MatchAlias function.
- If MatchAlias identifies a single target, it sets a flag telling you whether or
- not the key information about the target file matches the information in the
- alias record. It is the responsibility of your application to update the record.
-
- The ResolveAlias and SelectAlias functions automatically update an alias record
- when the key information about the target they return does not match the record.
-
- _______________________________________________________________________________
-
- æKY Storing…and…Retrieving…Alias…Records
- æC »Storing and Retrieving Alias Records Alias Manager
- _______________________________________________________________________________
-
- Alias records are stored as resources of type 'alis'.
-
- CONST rAliasType = 'alis'
-
- To store and retrieve alias records, use the standard Resource Manager functions
- described in the Resource Manager chapter of Volume I.
-
- _______________________________________________________________________________
-
- æKY Alias…Manager…Routines
- æC »ALIAS MANAGER ROUTINES Alias Manager
- _______________________________________________________________________________
-
- This section describes the routines you use to create, update, read, and resolve
- alias records.
-
- All Alias Manager routines use file system specification records (FSSpec
- records) to identify files, folders, and volumes. To create a FSSpec record,
- call the function MakeFSSpec, described in the File Manager chapter of this
- volume.
-
- The Alias Manager routines can return the result codes listed in this section or
- any other applicable file system or memory management result codes. The file
- system result codes are listed in the File Manager chapter of Volume IV, and the
- memory management result codes are listed in the Memory Manager chapter of this
- volume.
-
- _______________________________________________________________________________
-
- æKY Creating…and…Updating…Alias…Records
- æC »Creating and Updating Alias Records Alias Manager
- _______________________________________________________________________________
-
- You use the NewAlias function to create an alias record.
-
- FUNCTION NewAlias (fromFile,target: FSSpecPtr; VAR alias: AliasHandle) : OSErr;
-
- NewAlias creates an alias record that describes the object specified in the
- target parameter. It fills in the record and puts a record handle in the alias
- parameter.
-
- The fromFile parameter represents the starting point for a relative search. This
- parameter can be either NIL or a pointer to a valid FSSpec record. If fromFile
- is NIL, the alias record does not include relative path information. Specify a
- value for fromFile only if you want NewAlias to record relative path
- information.
-
- The target parameter points to a FSSpec record for the file, folder, or volume
- to be described by the alias record.
-
- The alias parameter is the handle for the newly created alias record. If the
- function fails to create an alias record, it sets alias to NIL.
-
- Result codes
- paramErr -50 The target parameter is NIL
-
-
- You use the UpdateAlias function to update an alias record.
-
- FUNCTION UpdateAlias (fromFile,target: FSSpecPtr; alias: AliasHandle; VAR
- wasChanged: Boolean) : OSErr;
-
- UpdateAlias updates the alias record pointed to by the alias parameter so that
- it describes the file, folder, or volume specified by the target parameter.
- UpdateAlias rebuilds the entire alias record.
-
- The fromFile parameter represents the starting point for a relative search. This
- parameter can be either NIL or a pointer to a valid FSSpec record. If fromFile
- is NIL, the updated alias record does not include relative path information.
- Specify a value for fromFile only if you want UpdateAlias to record relative
- path information.
-
- The target parameter is the target of the alias record. This parameter must
- point to a valid canonical file specification record.
-
- The alias parameter points to the alias record to be updated.
-
- If the newly constructed alias record is exactly the same as the old one,
- UpdateAlias sets the wasChanged parameter to FALSE. Otherwise, it sets it to
- TRUE. Check this parameter to determine whether you need to save an updated
- record.
-
- Result codes
- paramErr -50 target, alias, or both are NIL, or the handle is corrupt
- _______________________________________________________________________________
-
- æKY Resolving…and…Reading…Records
- æC »Resolving and Reading Records Alias Manager
- _______________________________________________________________________________
-
- You use the ResolveAlias function to resolve an alias.
-
- FUNCTION ResolveAlias (fromFile: FSSpecPtr; alias: AliasHandle; VAR target:
- FSSpec; VAR wasChanged: Boolean) : OSErr;
-
- If the resolution is successful, ResolveAlias returns the FSSpec record for the
- target filename through the target parameter, updates the alias record if
- necessary, and reports whether or not the record was updated through the
- wasChanged parameter. If the target object is on an unmounted AppleShare volume,
- ResolveAlias automatically mounts the volume. If the target is on an unmounted,
- ejectable volume, ResolveAlias displays a switch-disk dialog box. ResolveAlias
- exits after it finds one acceptable target.
-
- The fromFile parameter represents the starting point for a relative search. This
- parameter can be either NIL or a valid FSSpec record. If fromFile is NIL,
- ResolveAlias does not perform a relative sesarch.
-
- The alias parameter points to the alias record to be resolved and, if necessary,
- updated.
-
- The Target parameter receives the FSSpec record of the target filename.
-
- If it updates the alias record, ResolveAlias sets the wasChanged parameter to
- TRUE. Otherwise, it sets it to FALSE. If the function returns an error code, it
- sets wasChanged to FALSE.
-
- Result codes
- nsvErr -35 The volume is not mounted
- fnfErr -43 No target was found
- paramErr -50 The alias parameter is NIL, or the handle is corrupt
-
-
- If you want the user to direct the search when an alias record cannot be
- resolved unambiguously, call the SelectAlias function.
-
- FUNCTION SelectAlias (fromFile: FSSpecPtr; fileTypeName: Str31; aliasFilter:
- ProcPtr; alias: AliasHandle; VAR target: FSSpec; VAR
- wasChanged: Boolean; filterProc: ProcPtr; callbackPtr:
- Ptr) : OSErr;
-
- If SelectAlias finds a single match for the record pointed to by the alias
- parameter, it behaves the same way as ResolveAlias. If SelectAlias finds no
- matches or more than one match for the record, the Alias Manager presents a
- modal dialog box that allows the user to direct the search and select the
- target. (See “User-Directed Search” for a description of the dialog box.)
-
- The fromFile parameter represents the starting point for a relative search. This
- parameter can be either NIL or a valid FSSpec. If fromFile is NIL, SelectAlias
- does not perform a relative search.
-
- The fileTypeName string is a descriptive name for the file type of the target
- object, intended to help the user select the correct target. It appears as part
- of the title of the dialog box.
-
- The aliasFilter parameter points to an optional filter function supplied by your
- application. The Alias Manager executes this function for each possible match
- that SelectAlias finds or after three seconds have elapsed without a match.
- Your filter function returns a Boolean value that determines whether the
- possible match is to be discarded (TRUE) or displayed (FALSE). It can also
- terminate the search. The function has three parameters.
-
- FUNCTION MySelectAliasFilter (paramBlock: CInfoPBPtr; VAR quitFlag: Boolean;
- callbackPtr: Ptr) : Boolean
-
- The paramBlock parameter points to the catalog information parameter block
- record (as returned by the File Manager function PBGetCatInfo) of the alias
- match. The Alias Manager sets this parameter to NIL if it is calling the
- function to give it the chance to terminate the search. (Do not use this
- pointer without checking for NIL.) Your filter function sets the quitFlag
- parameter to terminate the search.
-
- The callbackPtr parameter is the same as the SelectAlias input parameter
- callbackPtr. This parameter allows your filter function to access your global
- or local data.
-
-
- The alias parameter points to the alias record to be resolved and, if
- necessary, updated.
-
- After the alias is resolved to a single target, the target parameter receives
- the FSSpec for the target.
-
- If it updates the alias record, SelectAlias sets the wasChanged parameter to
- TRUE. Otherwise, it sets it to FALSE. If the function returns an error code, it
- sets wasChanged to FALSE.
-
- The filterProc parameter points to your application’s optional event-filtering
- function, to be called by ModalDialog. (SelectAlias calls ModalDialog when it
- displays the SelectAlias dialog box. For a description of the ModalDialog
- procedure, see the Dialog Manager chapter of Volume I.) The filterProc parameter
- is similar to the same parameter in the Standard File Package procedure
- SFPGetFile. The function pointed to by filterProc must be the same as the one
- you would pass directly to ModalDialog in its filterProc parameter, except that
- it takes an additional fourth argument, which is the callbackPtr parameter as
- passed to the SelectAlias routine. This option allows your filter function to
- access the value of callbackPtr to retrieve your data.
-
- The callbackPtr parameter contains whatever data you specify. Use this parameter
- to pass information to your filter function.
-
- Result codes
- fnfErr -43 No target was found
- paramErr -50 target, alias, or both are NIL, or the handle is corrupt
- userCanceledErr -128 The user canceled the operation
-
- You use the MatchAlias function to identify a list of possible matches and pass
- the list through a selection filter. The filter can pass more than one possible
- match.
-
- FUNCTION MatchAlias (fromFile: FSSpecPtr; rulesMask: LongInt; alias:
- AliasHandle;
- VAR aliasCount: Integer; aliasList: FSSpecListPtr; VAR
- needsUpdate: Boolean; aliasFilter: ProcPtr; callbackPtr:
- Ptr) : OSErr;
-
- MatchAlias resolves the alias record pointed to by the alias parameter and
- returns a list of FSSpec records in the structure pointed to by the aliasList
- parameter. If it identifies more than one possible target, MatchAlias places in
- the aliasCount parameter the number of candidates in aliasList. MatchAlias
- follows the rules specified by the rulesMask parameter. If it resolves the alias
- to an object other than the one stored in the alias record or if it returns a
- list of possible candidates, it sets the needsUpdate flag to TRUE. Your
- application is responsible for calling UpdateAlias if necessary after the target
- is identified.
-
- The fromFile parameter represents the starting point for a relative search. This
- parameter can be either NIL or a valid FSSpec record. If fromFile is NIL,
- MatchAlias does not perform a relative search.
-
- The rulesMask parameter specifies a set of rules to guide the resolution. Pass
- the sum of all of the rules you want to invoke.
-
- Constant Description
-
- kARMmountVol Automatically try to mount the target’s volume if it is not
- mounted. If this rule is not set, and if the target’s volume is
-
- not mounted, MatchAlias returns nsvErr.
-
- kARMmultVols Search all mounted volumes. The search begins with the volume on
-
- which the target resided when the record was created.
-
- kARMsearch Search quickly for the alias, using the fast-search algorithm.
-
- kARMsearchMore Search further, using the slow-search algorithm.
-
- The further search uses the File Manager function CatSearch to
- match criteria such as creation date, type, and creator.
- CatSearch is available only on HFS volumes. When searching MFS
- volumes or AppleShare volumes running older system software,
- MatchAlias performs a recursive, indexing search using creation
- date, type, and creator.
-
- If both kARMsearch and kARMsearchMore are set, MatchAlias
- performs a fast search followed by a slow search.
-
- The alias parameter points to the alias record to be resolved.
-
- Your application can specify a maximum number of possible matches by setting the
- aliasCount parameter. MatchAlias sets the aliasCount parameter to the number of
- entries in the list of possible matches.
-
- The aliasList parameter points to the array that holds the results of the
- search.
-
- If MatchAlias resolves the alias to a target whose key information is different,
- or if it returns a list of possible candidates, it sets the needsUpdate flag to
- TRUE. Otherwise, it sets it to FALSE.
-
- The aliasFilter parameter points to a filter function supplied by your
- application. The Alias Manager executes this function for each possible match
- that MatchAlias finds or after three seconds have elapsed without a match. Your
- filter function returns a Boolean value that determines whether the possible
- match is discarded (TRUE) or added to the list of possible targets (FALSE). It
- can also terminate the search. The function has three parameters.
-
- FUNCTION MyMatchAliasFilter (paramBlock: CInfoPBPtr; VAR quitFlag: Boolean;
- callbackPtr: Ptr): Boolean
- The paramBlock parameter points to the catalog information parameter block
-
- record (as returned by the File Manager function PBGetCatInfo) of the alias
- match. The Alias Manager sets this parameter to NIL if it is calling the
- function to give it the chance to terminate the search. (Do not use this
- pointer without checking for NIL.) Your filter function sets the quitFlag
- parameter to terminate the search.
-
- The callbackPtr parameter is the same as the MatchAlias input parameter
- callbackPtr. This parameter allows your filter function to access your global
-
- or local data.
-
-
- The callbackPtr parameter contains whatever data you specify. Use this
- parameter to pass information to your filter function.
-
- Result codes
- nsvErr -35 The volume is not mounted
- fnfErr -43 No target was found
- paramErr -50 target, alias, or both are NIL, or the handle is corrupt
- userCanceledErr -128 The user canceled the operation
-
-
- You can use the GetAliasInfo function to read information from an alias record.
-
- FUNCTION GetAliasInfo (alias: AliasHandle; index: AliasInfoType; VAR theString:
- Str63 ) : OSErr;
-
- GetAliasInfo retrieves the information specified by the index parameter from the
- record pointed to by the alias parameter and places it in the parameter
- theString.
-
- The alias parameter points to the alias record to be read.
-
- The index parameter specifies the kind of information to be retrieved. If index
- is a positive integer, GetAliasInfo retrieves the parent folder that has the
- same hierarchical level as the index parameter. You can therefore assemble the
- names of the target and all of its parent folders by making repeated calls to
- GetAliasInfo with incrementing index values, starting with a value of 0. When
- index is greater than the hierarchical level of the root, GetAliasInfo returns
- an empty string. You can also set index to one of these five values:
-
- Constant Value Description
- asiZoneName -3 If the record represents an object on an AppleShare volume,
-
- retrieve the server’s zone name. Otherwise, return an empty
- string.
-
- asiServerName -2 If the record represents an object on an AppleShare volume,
-
- retrieve server name. Otherwise, return an empty string.
-
- asiVolumeName -1 Return the name of the volume on which the represented
- object resides.
-
- asiAliasName 0 Return the name of the object represented by the record.
-
- asiParentName 1 Return the name of the parent folder of the object
- represented by the record. If the object is a volume,
- return the volume name.
-
- GetAliasInfo places the requested information in the parameter theString.
-
- GetAliasInfo returns the information stored in the alias record, which might not
- be current.
-
- Result codes
- paramErr -50 alias, theString, or both are NIL; the index is less
- than asiZoneName; or the handle is corrupt
- _______________________________________________________________________________
-
- æKY Summary…of…the…Alias…Manager
- æC »SUMMARY OF THE ALIAS MANAGER Alias Manager
- _______________________________________________________________________________
-
- The following cards summarize the constants, data types, and routines for the
- Alias Manager.
- _______________________________________________________________________________
-
- æKY Alias…Constants
- æC »Constants Alias Manager
- _______________________________________________________________________________
-
- CONST
- rAliasType = 'alis'; {resource type for saved alias records}
-
- {rulesMask for MatchAlias}
- kARMmountVol = $0001; {mount the volume automatically}
- kARMmultVols = $0008; {search on multiple volumes}
- kARMsearch = $0100; {search quickly}
- kARMsearchMore = $0200; {search further}
-
- {index values for GetAliasInfo}
- asiZoneName = -3;
- asiServerName = -2;
- asiVolumeName = -1;
- asiAliasName = 0;
- asiParentName = 1;
- _______________________________________________________________________________
-
- æKY Alias…Data…Types
- æC »Data Types Alias Manager
- _______________________________________________________________________________
-
- TYPE
- FSSpecArrayPtr = ^FSSpecArray;
- FSSpecArray = ARRAY[0..0] OF FSSpec;
-
- AliasHandle = ^AliasPtr;
- AliasPtr = ^AliasRecord;
- AliasRecord =
- RECORD
- userType: OSType;
- aliasSize: Integer;
- {variable-length private data}
- END;
- AliasInfoType = Integer;
- _______________________________________________________________________________
-
- æKY Alias…Routines
- æC »Routines Alias Manager
- _______________________________________________________________________________
-
- Creating and Updating Records
-
- FUNCTION NewAlias (fromFile,target: FSSpecPtr; VAR alias: AliasHandle) : OSErr;
- FUNCTION UpdateAlias (fromFile,target: FSSpecPtr; alias: AliasHandle; VAR
- wasChanged: Boolean) : OSErr;
-
- Resolving and Reading Records
-
- FUNCTION ResolveAlias (fromFile: FSSpecPtr; alias: AliasHandle; VAR target:
- FSSpec; VAR wasChanged: Boolean) : OSErr;
- FUNCTION SelectAlias (fromFile: FSSpecPtr; fileTypeName: Str31; aliasFilter:
- ProcPtr; alias: AliasHandle; VAR target: FSSpec; VAR
- wasChanged: Boolean; filterProc: ProcPtr; callbackPtr:
- Ptr)
- : OSErr;
- FUNCTION MatchAlias (fromFile: FSSpecPtr; rulesMask: LongInt; alias:
- AliasHandle;
- VAR aliasCount: Integer; aliasList: FSSpecListPtr; VAR
- needsUpdate: Boolean; aliasFilter: ProcPtr; callbackPtr:
- Ptr) : OSErr;
- FUNCTION GetAliasInfo (alias: AliasHandle; index: AliasInfoType; VAR theString:
- Str63; ) : OSErr;
- _______________________________________________________________________________
-
- æKY Alias…Result…Codes
- æC »Result Codes Alias Manager
- _______________________________________________________________________________
-
- nsvErr -35 The volume is not mounted
- fnfErr -43 No target was found
- paramErr -50 One or more parameters is NIL, or a handle is corrupt
- userCanceledErr -128 The user canceled the operation
- _______________________________________________________________________________
-
- æKY Assembly-Language…Information…for…Alias
- æC »Assembly-Language Information Alias Manager
- _______________________________________________________________________________
-
- Constants
-
- ;Resource type for alias records
- rAliasType .EQU 'alis'
-
- ;rulesMask for MatchAlias
- kARMmountVol .EQU $00000001; {mount the volume automatically}
- kARMmultVols .EQU $00000008; {search on multiple volumes}
- kARMsearch .EQU $00000100; {search quickly}
- kARMsearchMore .EQU $00000200; {search further}
-
- ;GetAliasInfo request types
- asiZoneName .EQU -3 ;get zone name
- asiServerName .EQU -2 ;get server name
- asiVolumeName .EQU -1 ;get volume name
- asiAliasName .EQU 0 ;get object name
- asiParentName .EQU 1 ;get parent folder name
-
- Alias Record Data Structure
- userType 4 bytes file type of target file
- aliasSize 2 bytes size of record in bytes
- {variable-length private data}
-
-
- _______________________________________________________________________________
-
-
- æKY AppleDesktopBus
- æC
- THE APPLE DESKTOP BUS
- _______________________________________________________________________________
-
- About…The…AppleDesktopBus…Chapter
- About…the…Apple…Desktop…Bus
- ADB…Manager…Routines
- Writing…ADB…Device…Drivers
- Summary…of…the…ADB
- _______________________________________________________________________________
-
-
-
- æKY About…The…AppleDesktopBus…Chapter
- æC »ABOUT THIS CHAPTER AppleDesktopBus
- _______________________________________________________________________________
-
- This chapter tells you how to accomplish low-level communication with peripheral
- devices that are connected to the Apple Desktop Bus (ADB).
-
- Reader’s guide: The standard mouse and keyboard drivers automatically take
- care of all required ADB access functions. When the user
- manipulates the mouse or keyboard, the system calls the
- appropriate driver and the application never uses the ADB
- Manager. Hence you need the information in this chapter only
- if you are writing a special driver, such as a driver for a
- new user-input device.
-
- The ADB is a simple local-area network that connects low-speed input-only devices to
- the operating system. In the Macintosh II and Macintosh SE computers, the ADB is used
- to communicate with one or more keyboards, the mouse, and other user input devices.
-
- Keys located on multiple keyboards are distinguished by the keyboard event message,
- as described in the Toolbox Event Manager chapter.
-
- Note: An ADB, using the same operating protocols, is also part of the
- Apple IIgs computer.
-
- This chapter contains three principal sections:
-
- • a description of the Apple Desktop Bus and how it works
- • a description of the ADB Manager. This section of system ROM contains
- the routines that a driver must use to access devices connected to the ADB.
- • a discussion of the special requirements for drivers that support
- devices connected to the ADB
-
- You should already be familiar with
-
- • the hardware interface to the Apple Desktop Bus, described in the
- Macintosh Family Hardware Reference
- • events generated by ADB keyboard devices (described in the Toolbox
- Event Manager chapter) if your driver communicates with one or more
- keyboards
-
- _______________________________________________________________________________
-
-
- æKY About…the…Apple…Desktop…Bus
- æC »ABOUT THE APPLE DESKTOP BUS AppleDesktopBus
- _______________________________________________________________________________
-
- The Apple Desktop Bus connects up to 16 low-speed input-only devices to the Macintosh
- II or Macintosh SE computer. Each device can maintain up to four variable-size registers,
- whose contents can be read from or written to by the ADB network. Each register may
- contain from two to eight bytes. Two of the device registers have an assigned meaning
- and a standardized format: register 0, used for interrupt information, and register
- 3, containing the device’s identification number. The other two device registers have
- no assigned meaning, and may have different meanings for read and write operations.
-
- The system communicates with the Apple Desktop Bus through the system’s Versatile
- Interface Adapter chip (VIA). The VIA is described in the Macintosh Hardware chapter.
-
- Warning: The ADB does not support connecting a device while the computer
- is running. The result may be to reinitialize all devices on the
- bus without informing the system.
-
- The system always controls the bus. It issues commands to specific devices on the bus
- and they respond by accepting data, sending data, or changing their configuration.
- These commands are discussed below.
-
- Note: Devices connected to the ADB contain their own single-chip
- microprocessors, which handle both device routines and the
- ADB interface. If the system sends commands to a device with
- a duty cycle of more than 50%, the device’s microprocessor
- may become overloaded.
-
- _______________________________________________________________________________
-
- »Bus Commands
-
- Each bus command consists of a byte that the system sends to a device connected to
- the ADB. Applications may place bus commands on the network by calling the routine
- ADBOp, discussed under “ADB Manager Routines” later in this chapter. There are four
- bus commands; their bit layouts are shown in Figure 1. All other bit layouts are
- reserved.
-
- •••Refer to Figure 1.•••
-
- Figure 1–ADB Command Formats
-
- The individual commands are discussed below.
-
- Warning: Values of the low bytes of the ADB command formats other than
- those shown in Figure 1 are reserved, and should not be used.
-
- »SendReset
-
- The SendReset command forces a hardware reset of all devices connected to the ADB.
- Such a reset clears all pending device actions and places the devices in their startup
- state. All devices are able to accept new ADB commands and user inputs immediately
- thereafter. All devices ignore the high-order four bits of the SendReset command.
-
- »Flush
-
- The Flush command flushes data from the single device specified by the network address
- in its high-order four bits. Network addresses are discussed below, under “Device
- Addressing”. It purges any pending user inputs and make the device ready to accept
- new commands and input data.
-
- »Listen
-
- The Listen command is used to send instructions to devices connected to the ADB. It
- transfers data from a buffer in system RAM to a register in the device specified by
- the network address in its high-order four bits. The device register is specified by
- the low-order two bits of the Listen command.
-
- »Talk
-
- The Talk command is used to fetch user inputs from devices connected to the ADB. It
- is the complement of the Listen command. It transfers data from a register in the
- device specified by the network address in its high-order four bits to a buffer in
- system RAM. The device register is specified by the low-order two bits of the Talk
- command.
-
- _______________________________________________________________________________
-
- »Device Registers
-
- Each device connected to the ADB contains four registers, each of which may store
- from two to eight bytes of data. Each register is identified by the value of the
- low-order two bits in a Listen or Talk command. Registers 0 and 3 have dedicated
- functions; registers 1 and 2 are used for purposes specific to each device, and need
- not be present in a device.
-
- Note: ADB device registers are virtual registers; they need not be
- implemented physically. The device firmware must only respond
- to register commands as if a register were present.
-
- »Register 0
-
- Device register 0 is reserved for input data. If the device has user-input data to be
- fetched, it places the data in register 0 and requests service. It continues to
- request service until the system retrieves its data. The system responds to data-input
- requests with the following polling sequence:
-
- • It generates a Talk command for register 0 in each device connected
- to the ADB.
- • If the device has data to send, it responds. The system does not
- poll the next device until the data is exhausted.
- • If the device has no data to send, or if its data is exhausted, the
- VIA generates an interrupt. The system then polls the next device.
- • This process continues until no devices request service.
-
- »Register 3
-
- Device register 3 is reserved for device identification data and operating flags.
- Application programs may set this data with Listen commands and read it with Talk
- commands. Register 3 stores 16 bits, divided into the fields shown in Figure 2.
-
- •••Refer to Figure 2.•••
-
- Figure 2–Format of Device Register 3
-
- Except for commands that contain certain reserved device handler ID values
- (listed below), every command to register 3 changes the entire register contents.
- Hence to change part of the register, you should first fetch its current contents
- with a Talk command and then send it an updated value with Listen. You can change
- part of the contents of register 3 by using special device handler ID values, as
- described below.
-
- The device handler ID field indicates the device’s type. With certain devices, an
- application can change the device’s mode of operation by sending it a new ID value.
- If the device supports the new mode, it stores the new value in this field.
-
- Warning: You are assigned handler IDs by Apple Software Licensing, so
- they do not conflict with the values of other devices that may
- be connected to the ADB at the same time.
-
- When certain reserved values are sent to the device handler ID field by a Listen
- command, they are not stored in the field; instead, they cause specific device actions.
- Hence these values cannot be used as device ID values. They are the following:
-
- Value Action
-
- $00 Change bits 8–13 of register 3 to match the rest of the command;
- leave Device Handler ID value unchanged.
- $FD Change Device Address to match bits 8–11 if the device activator
- has been depressed; leave Device Handler ID value and flags unchanged.
- $FE Change Device Address to match bits 8–11 if the result produces no
- address duplication on the bus; leave Device Handler ID value and
- flags unchanged.
- $FF Initiate device self-test. If self-test succeeds, leave register 3
- unchanged; if self-test fails, clear Device Handler ID field to $00.
-
- Other Device Handler ID values may be stored in the field.
-
- Note: Device Handler ID values below $20 are reserved by Apple.
-
- The Device Address field indicates the device’s location within the 16 possible
- device locations of the ADB. An application may change its value with a Listen command.
- When this field is interrogated with a Talk command, it returns a random value. This
- helps you separate multiple devices that have the same ADB address; for further
- information, see “Device Addressing”, below.
-
- The Service Request Enable bit is set by the device to request an interrupt poll.
-
- _______________________________________________________________________________
-
- »Device Addressing
-
- There are 16 possible direct addresses, $00–$0F, for devices connected to the ADB.
- However, it is possible to connect more than one device to an address; this might
- happen, for example, in a system with two alternate keyboards.
-
- When several devices share a single ADB address, but there are free addresses available
- in the net, the system will automatically reassign addresses until they are all
- different. It will do this every time the ADB Manager is initialized or reinitialized.
- To find out a device’s new address, use the calls GetIndADB or GetADBInfo, described
- later in this chapter.
-
- _______________________________________________________________________________
-
- »Standard ADB Device Drivers
-
- The Macintosh II and Macintosh SE systems contain two standard ADB drivers:
-
- • the mouse driver, which supports the ADB mouse. The Apple mouse
- has an original ADB address of 3.
- • the universal keyboard driver, which supports all Apple ADB keyboards.
- The Apple keyboard has an original ADB address of 2, with a Device
- Handler ID of 1 for the Macintosh II keyboard and 2 for the Apple
- Extended Keyboard. These keyboards are described in the Toolbox
- Event Manager chapter.
-
- These drivers reside in the system ROM. In addition, ADB address 0 is reserved for
- the ADB chip itself. You can change the ADB addresses of the mouse or keyboard, as
- described above under “Device Registers,” but Apple does not recommend doing so.
-
- Assembly-language note: The ADB address of the keyboard on which the
- last-typed character was entered is now stored
- in the global variable KbdLast. The type of the
- keyboard on which the last-typed character was
- entered is stored in the global variable KbdType.
- The value of KbdType is the Device Handler ID
- value in Register 3 of the device; values below
- $20 are reserved by Apple.
-
- The requirements for writing new ADB device drivers are discussed later in this
- chapter.
-
- _______________________________________________________________________________
-
-
- æKY ADB…Manager…Routines
- æC »ADB MANAGER ROUTINES AppleDesktopBus
- _______________________________________________________________________________
-
- The ADB Manager consists of six routines located in the 256K ROM. You would use them
- only if you needed to access bus devices directly or communicate with a special
- device.
-
- Some of these routines access and update information in the ADB device table, a
- structure placed in the system heap by ROM code during system startup. It lists for
- each device the device’s type, its original ADB address, its current ADB address, the
- address of the routine that services the device, and the address of the area in RAM
- used for temporary data storage by its driver. The ADB device table is accessible
- only through ADB Manager routines.
-
- PROCEDURE ADBReInit;
-
- Trap macro _ADBReInit
-
- ADBReInit reinitializes the entire Apple Desktop Bus. It clears the ADB device table
- to zeros and places a SendReset command on the bus to reset all devices to their
- original addresses. ADBReInit has no parameters.
-
- Because it does not deallocate ADB resources on the system heap, ADBReInit should not
- be used for routine bus initialization. Apple strongly recommends against adding
- devices while the system is running; therefore, you should never call ADBReInit.
-
- ADBReInit also calls a routine pointed to by the low memory global JADBProc
- at the beginning and end of its execution. You can insert your own
- preprocessing/postprocessing routine by changing the value of JADBProc; ADBReInit
- conditions it by setting D0 to 0 for preprocessing and to 1 for postprocessing. Your
- procedure must restore the value of D0 and branch to the original value of JADBProc
- on exit. JADBProc should be used to de-allocate memory used by the driver (see
- MacDTS Sample Code “TbltDrvr” for an example), and then it should chain to the procedure
- originally found in JADBProc.
-
- The complete ADBReInit sequence is therefore the following:
-
- • JSR to JADBProc with D0 set to 0
- • reinitialize the Apple Desktop Bus
- • clear the ADB device table
- • JSR to JADBProc with D0 set to 1
-
- FUNCTION ADBOp (data: Ptr; compRout: ProcPtr; buffer: Ptr;
- commandNum: INTEGER) : OSErr;
-
- Trap macro _ADBOp
-
- On entry: A0: pointer to parameter block
- D0: commandNum (byte)
-
- Parameter block
- --> 0 buffer pointer
- --> 4 compRout pointer
- --> 8 data pointer
-
- On exit: D0: result code (byte)
-
- The completion routine pointed to by compRout will be passed the following parameters
- on entry:
-
- D0: commandNum (byte)
- A0: pointer to buffer, data stored as a Pascal string (maximum
- 8 bytes data preceded by one length byte)
- A1: pointer to completion routine (compRout)
- A2: pointer to optional data area (data)
-
- ADBOp transmits over the bus the command byte whose value is given by commandNum. The
- structure of the command byte is given earlier in Figure 1. ADBOp executes only when
- the ADB is otherwise idle; otherwise it is held in a command queue. It returns an
- error if the command queue is full. The length of the data buffer pointed to by
- buffer is contained in its first byte, like a Pascal string. The optional data area
- pointed to by data is for local storage by the completion routine pointed to by
- compRout. ADBop should be used sparingly; it is not intended for polling a device.
- The host automatically polls devices with data to deliver.
-
- Result codes noErr No error
- –1 Unsuccessful completion
-
- FUNCTION CountADBs: INTEGER;
-
- Trap macro _CountADBs
-
- On exit: D0: number of devices (byte)
-
- CountADBs returns a value representing the number of devices connected to the ADB by
- counting the number of entries in the device table. It has no arguments and returns
- no error codes.
-
- FUNCTION GetIndADB (VAR info: ADBDataBlock;
- devTableIndex: INTEGER) : ADBAddress;
-
- Trap macro _GetIndADB
-
- On entry: A0: pointer to parameter block
- D0: entry index number; range = 1..CountADBs (byte)
-
- Parameter block
- <-- 0 device type byte (handler ID)
- <-- 1 original ADB address byte
- <-- 2 service routine address pointer (compRout)
- <-- 6 data area address pointer (data)
-
- On exit: D0: positive value: current ADB address (byte)
- negative value: error code (byte)
-
- GetIndADB returns information from the ADB device table entry whose index number is
- given by devTableIndex. ADBDataBlock has this form:
-
- TYPE ADBDataBlock =
- PACKED RECORD
- devType: SignedByte; {device type (handler ID)}
- origADBAddr: SignedByte; {original ADB address}
- dbServiceRtPtr: Ptr; {service routine address (compRout)}
- dbDataAreaAddr: Ptr {data area address (data)}
- END;
-
- GetIndADB returns the current ADB address of the device. If it is unable to complete
- execution successfully, GetIndADB returns a negative value.
-
- FUNCTION GetADBInfo (VAR info: ADBDataBlock; ADBAddr: ADBAddress) : OsErr;
-
- Trap macro _GetADBInfo
-
- On entry: A0: pointer to parameter block
- D0: ADB address of the device (byte)
-
- Parameter block
- <-- 0 device handler ID byte
- <-- 1 original ADB address byte
- <-- 2 service routine address pointer (compRout)
- <-- 6 data area address pointer (data)
-
- On exit: D0: result code (byte)
-
- GetADBInfo returns information from the ADB device table entry of the device whose
- ADB address is given by ABDAddr. The structure of ADBDataBlock is given above under
- “GetIndADB”.
-
- Result codes noErr No error
-
- FUNCTION SetADBInfo (VAR info: ADBSetInfoBlock; ADBAddr: ADBAddress) : OsErr;
-
- Trap macro _SetADBInfo
-
- On entry: A0: pointer to parameter block
- D0: ADB address of the device (byte)
-
- Parameter block
- --> 0 service routine address pointer (compRout)
- --> 4 data area address pointer (data)
-
- On exit: D0: result code (byte)
-
- SetADBInfo sets the service routine address and the data area address in the ADB
- device table entry for the device whose ADB address is given by ABDAddr. ADBSetInfoBlock
- has this form:
-
- TYPE ADBSetInfoBlock =
- RECORD
- siServiceRtPtr: Ptr; {service routine address (compRout)}
- siDataAreaAddr: Ptr {data area address (data)}
- END;
-
- Result codes noErr No error
-
- Warning: You should send a Flush command to the device after calling it
- with SetADBInfo, to prevent it sending old data to the new data
- area address.
-
- _______________________________________________________________________________
-
-
- æKY Writing…ADB…Device…Drivers
- æC »WRITING ADB DEVICE DRIVERS AppleDesktopBus
- _______________________________________________________________________________
-
- Drivers for devices connected to the ADB have the following special requirements:
-
- • Each ADB device driver must reside in a resource of type 'ADBS'.
- (An example 'ADBS' resource is available in MacDTS Sample Code
- “TbltDrvr.”) This type has two sections: initialization and driver code.
- • The initialization section of each ADB device driver must support the
- installation procedure described below.
-
- When the system calls an ADB device driver, it passes it the following values:
-
- • Register A0 points to the data buffer, which is formatted as a
- Pascal string (buffer).
- • Register A1 points to the driver’s completion routine (compRout).
- • Register A2 points to the optional data area (data).
- • Register D0 contains the ADB command that resulted in the driver
- being called (commandNum).
-
- The ADB driver should handle the ADB command passed to it and store any resulting
- input data by an appropriate action, such as by posting an event or moving the cursor.
-
- Note: Events posted from keyboards connected to the ADB now have an
- expanded structure. For more information, see the Toolbox Event
- Manager chapter.
-
- _______________________________________________________________________________
-
- »Installing an ADB Driver
-
- The Start Manager (described in this volume) finds all the ADB devices connected to
- the system and places their device types and ADB addresses in the ADB device table.
- It then calls the initialization section of each ADB device driver by executing the
- initialization code in its 'ADBS' resource.
-
- As a minimum, the initialization section of each ADB device driver must do the following:
-
- • The driver must allocate all the memory required by the driver code
- in one or more nonrelocatable blocks in the system heap area.
- • The driver must install its own preprocessing/postprocessing routine
- (if any) as described above under “ADBReInit”.
- • Finally, the driver must initialize the service routine address and
- data area address of its entry in the ADB device table, using SetADBInfo.
-
- _______________________________________________________________________________
-
-
- æKY Summary…of…the…ADB
- æC »SUMMARY OF THE ADB MANAGER AppleDesktopBus
- _______________________________________________________________________________
-
- Data Types
-
- TYPE
- ADBDataBlock =
- PACKED RECORD
- devType: SignedByte; {Handler ID}
- origADBAddr: SignedByte; {original ADB address}
- dbServiceRtPtr: Ptr; {service routine address (compRout)}
- dbDataAreaAddr: Ptr {data area address (area)}
- END;
-
- ADBSetInfoBlock =
- RECORD
- siServiceRtPtr: Ptr; {service routine address}
- siDataAreaAddr: Ptr {data area address}
- END;
-
- _______________________________________________________________________________
-
- Routines
-
- Initializing the ADB Manager
-
- PROCEDURE ADBReInit;
-
- Communicating Through the ADB
-
- FUNCTION ADBOp (data: Ptr; compRout: ProcPtr; buffer: Ptr;
- commandNum: INTEGER) : OSErr;
-
- Getting ADB Device Information
-
- FUNCTION CountADBs: INTEGER;
- FUNCTION GetIndADB (VAR info: ADBDataBlock;
- devTableIndex: INTEGER) : ADBAddress;
- FUNCTION GetADBInfo (VAR info: ADBDataBlock; ADBAddr: ADBAddress) : OsErr;
-
- Setting ADB Device Information
-
- FUNCTION SetADBInfo (VAR info: ADBSetInfoBlock; ADBAddr: ADBAddress) : OsErr;
-
- _______________________________________________________________________________
-
- Assembly-Language Information
-
- Variables
-
- JADBProc Pointer to ADBReInit preprocessing/postprocessing routine
- KbdLast ADB address of the keyboard last used (byte)
- KbdType Keyboard type of the keyboard last used (byte)
-
- Routines
-
- Trap macro On entry On Exit
-
- _ADBReInit
-
- _ADBOp A0: pointer to parameter block D0: result code (byte)
- buffer (pointer)
- compRout (pointer)
- data (pointer)
- D0: commandNum (byte)
-
- _CountADBs D0: result code (byte)
-
- _GetIndADB A0: pointer to parameter block D0: positive value:
- device type (byte) current ADB
- original ADB address (byte) address (byte)
- service routine address (pointer) negative value:
- data area address (pointer) error code (byte)
- D0: entry index number;
- range = 1..CountADBs (byte)
-
- _GetADBInfo A0: pointer to parameter block D0: result code (byte)
- device handler ID (byte)
- original ADB address (byte)
- service routine address (pointer)
- data area address (pointer)
- D0: current ADB address of the device (byte)
-
- _SetADBInfo A0: pointer to parameter block D0: result code (byte)
- service routine address (pointer)
- data area address (pointer)
- D0: current ADB address of the device (byte)
-
- Further Reference:
- _______________________________________________________________________________
- Toolbox Event Manager
- Technical Note #143, Don’t Call ADBReInit on the SE with System 4.1
- Technical Note #160, Key Mapping
- Technical Note #206, Space Aliens Ate My Mouse
- “Macintosh Family Hardware Reference”
-
-
- æKY AppleTalkManager
- æC
- _______________________________________________________________________________
-
- APPLETALK MANAGER
- _______________________________________________________________________________
-
- About…the…AppleTalk…Manager…Vol…VI…Chapter
- About…the…AppleTalk…Manager…Vol…VI
- Changes…to…the…AppleTalk…Manager…Vol…VI
- AppleTalk…Protocols…Vol…VI
- AppleTalk…Device…Drivers,…'adev'…Files,…and…the…LAP…Manager
- Using…the…AppleTalk…Manager…Vol…VI
- Determining…Whether…AppleTalk…Phase…2…Drivers…Are…Present
- Determining…Which…AppleTalk…Protocol…to…Use
- The….MPP…Driver
- Getting…Information…About…the….MPP…Driver
- A…New…NBP…Wildcard…Character
- The…LAP…Manager
- The…AppleTalk…Transition…Queue
- Adding…and…Removing…AppleTalk…Transition…Queue…Entries
- Sending…Messages…to…the…AppleTalk…Transition…Queue
- How…the…AppleTalk…Manager…Calls…Your…Transition…Queue…Routine
- The…LAP…Manager…802.2…Protocol
- Attaching…and…Detaching…802.2…Protocol…Handlers
- AppleTalk…Data…Stream…Protocol…(ADSP)
- Using…ADSP
- The…ADSP…Connection…Control…Block
- The….DSP…Parameter…Block
- Opening…and…Maintaining…an…ADSP…Connection
- Creating…and…Using…a…Connection…Listener
- Writing…a…User…Routine…For…Connection…Events
- DSP…Driver…Commands
- Establishing…and…Terminating…an…ADSP…Connection
- Establishing…and…Terminating…an…ADSP…Connection…Listener
- Maintaining…an…ADSP…Connection
- The….ATP…Driver
- Canceling…All…Calls…to…the…ATPGetRequest…Function
- Setting…the…Timeout…Value…For…the…ATP…Release…Timer
- The….XPP…Driver
- Using…the….XPP…Driver…to…Obtain…Zone…Information
- XPP…Driver…Routines
- The….ENET…Driver
- Changing…the…Ethernet…Hardware…Address
- Opening…the….ENET…Driver
- Using…a…Write-Data…Structure…to…Transmit…Ethernet…Data
- Using…the…Default…Ethernet…Protocol…Handler…to…Read…Data
- Using…Your…Own…Ethernet…Protocol…Handler…to…Read…Data
- How…the….ENET…Driver…Calls…Your…Protocol…Handler
- How…Your…Protocol…Handler…Calls…the….ENET…Driver
- ENET…Driver…Routines
- Attaching…and…Detaching…an…Ethernet…Protocol…Handler
- Writing…and…Reading…Packets…Using…the…Default…Protocol…Handler
- Adding…and…Removing…Ethernet…Multicast…Addresses
- Summary…of…the…AppleTalk…Manager…Vol…VI
- AppleTalk…Constants
- AppleTalk…Data…Types
- AppleTalk…Routines
- AppleTalk…Result…codes
- Assembly-language…Information…for…AppleTalk
-
- About…The…AppleTalkManager…Chapter
- AppleTalk…Protocols
- AppleTalk…Transaction…Protocol
- About…the…AppleTalk…Manager
- Calling…the…AppleTalk…Manager…from…Pascal
- New…AppleTalk…Manager…Pascal…Interface
- Picking…a…Node…Address…in…the…Server…Range
- Sending…Packets…to…One’s…Own…Node
- ATP…Driver…Changes
- Name…Binding…Protocol…Changes
- Variable…Resources
- Calling…the…AppleTalk…Manager…from…Assembly…Language
- Extended…Protocol…Package…Driver
- Calling…the….XPP…Driver
- Protocol…Handlers…and…Socket…Listeners
- Summary…of…the…AppleTalk…Manager
- _______________________________________________________________________________
-
-
- æKY About…the…AppleTalk…Manager…Vol…VI…Chapter
- æC »ABOUT THIS CHAPTER AppleTalk Manager
- _______________________________________________________________________________
-
- AppleTalk is a communication network system including personal computer
- workstations, computers acting as file servers and print servers, printers, and
- a variety of types of communication hardware and software. The AppleTalk Manager
- provides an interface to this communication network system for applications
- running on Macintosh computers. This chapter describes the changes to the
- AppleTalk Manager introduced as AppleTalk Phase 2 and included with system
- software version 7.0. This chapter supplements the information in the AppleTalk
- Manager chapters of Inside Macintosh, Volumes II and V.
-
- This chapter describes
- • new routines for the .MPP, .ATP, and .XPP device drivers
-
- • a new wildcard character for use with the Name-Binding Protocol
-
- • a new system queue, called the AppleTalk Transition Queue
-
- • a new set of operating system utilities, collectively called the LAP
- Manager.
-
- • the .ENET driver and the routines your application can use to control
- this driver
-
- • the application interface routines provided by a new AppleTalk protocol,
- the AppleTalk Data Stream Protocol
-
- Together with the AppleTalk Manager chapters of Volumes II and V, this chapter
- describes the routines that your application can use to send and receive
- information within an AppleTalk network system . Because the AppleTalk network
- system includes both hardware and software, and because the software includes
- not only the AppleTalk Manager but file servers, print servers, internet
- routers, drivers for circuit cards, and so forth, the information in Inside
- Macintosh constitutes only a small part of the body of literature documenting
- AppleTalk.
-
- For a detailed description of AppleTalk protocols, see Inside AppleTalk. For a
- complete description of the LAP Manager, EtherTalk, and alternate AppleTalk
- connections, see the AppleTalk Connections Programmer’s Guide. To learn how to
- install and operate an AppleTalk internet, see the AppleTalk Internet Router
- Administrator’s Guide and the AppleTalk Phase 2 Introduction and Upgrade Guide.
- For an introduction to the hardware and software of an entire AppleTalk network,
- see Understanding Computer Networks and the AppleTalk Network System Overview.
- For information on designing circuit cards and device drivers for Macintosh
- computers, see Designing Cards and Drivers for the Macintosh Family.
-
- You can install the Phase 2 versions of the AppleTalk drivers on any Macintosh
- computer other than the Macintosh XL, Macintosh 128K, Macintosh 512K, and
- Macintosh 512K enhanced computers. If you want to provide AppleTalk Phase 2
- device drivers with your product, you must obtain a license from Apple Software
- Licensing.
-
- _______________________________________________________________________________
-
- æKY About…the…AppleTalk…Manager…Vol…VI
- æC »ABOUT THE APPLETALK MANAGER AppleTalk Manager
- _______________________________________________________________________________
-
- The AppleTalk Manager includes a number of protocols that are implemented in
- various device drivers. The AppleTalk Manager also includes the LAP Manager,
- which interfaces the AppleTalk data links to the AppleTalk protocols; and
- hardware device drivers for specific networks. The AppleTalk data links are
- contained in files of type 'adev', sometimes referred to as 'adev' files. This
- section lists the new features that have been introduced as AppleTalk Phase 2,
- describes the organization of the AppleTalk Manager, and briefly discusses what
- each component of the AppleTalk Manager does.
-
-
- _______________________________________________________________________________
-
- æKY Changes…to…the…AppleTalk…Manager…Vol…VI
- æC »Changes to the AppleTalk Manager AppleTalk Manager
- _______________________________________________________________________________
-
- The features that have been introduced as AppleTalk Phase 2 include
-
- • a new .MPP driver function that returns information about the .MPP driver
-
- • a new protocol, the AppleTalk Data Stream Protocol (ADSP), which provides
- full-duplex data stream communications for use by applications; see
- “AppleTalk Data Stream Protocol”
-
- • improvements to the Zone Information Protocol (ZIP) that allow a single
- network (other than LocalTalk) to contain more than one zone; see
- “Obtaining Zone Information.”
-
- • new functions for the .XPP device driver that provide information from
- ZIP about zones; see “The .XPP Driver”
-
- • a new Name Binding Protocol (NBP) wildcard character that can substitute
- for one or more characters in AppleTalk names; see “A New NBP Wildcard
- Character”
-
- • the AppleTalk Transition Queue, an operating system queue that can notify
- your application each time an AppleTalk driver is opened or closed, or
- certain other transitions occur; see “The AppleTalk Transition Queue”
-
- • the LAP Manager, a new set of operating system utilities that provide a
- standard interface between the AppleTalk protocols and the data links
- used by Appletalk, such as EtherTalk, LocalTalk, and TokenTalk; see “The
- LAP Manager”
-
- • the .ENET driver, an Ethernet driver for the EtherTalk NuBus card that is
- manufactured by Apple Computer, Inc.; see “The .ENET Driver”
-
- • an implementation of the IEEE 802.2 protocol, which allows you to attach
- and detach your own protocol handlers for EtherTalk and TokenTalk data
- packets; see “The LAP Manager 802.2 Protocol”
-
- • new .ATP driver functions that allow you to set a value for the .ATP
- release timer and to cancel all pending asynchronous calls to the
- ATPGetRequest function for a specific socket; see “The .ATP Driver”
- _______________________________________________________________________________
-
- æKY AppleTalk…Protocols…Vol…VI
- æC »AppleTalk Protocols AppleTalk Manager
- _______________________________________________________________________________
-
- The AppleTalk Manager comprises the following protocols:
-
- • LocalTalk Link Access Protocol (LLAP)
- • Datagram Delivery Protocol (DDP)
- • Routing Table Maintenance Protocol (RTMP)
- • AppleTalk Transaction Protocol (ATP)
- • Name-Binding Protocol (NBP)
- • AppleTalk Echo Protocol (AEP)
- • Zone Information Protocol (ZIP)
- • AppleTalk Session Protocol (ASP)
- • AppleTalk Data Stream Protocol (ADSP)
- • AppleTalk Filing Protocol (AFP)
-
- The EtherTalk Link Access Protocol, TokenTalk Link Access Protocol, and other
- Link Access Protocols provide interfaces between the AppleTalk Manager and the
- different types of data link hardware used by AppleTalk.
-
- Note: The LocalTalk Link Access Protocol (LLAP) was originally called the
- AppleTalk Link Access Protocol (ALAP). It has been renamed to avoid confusion
- with the EtherTalk Link Access Protocol and other link access protocols.
-
- Figure 29-1 shows the relationships among the various AppleTalk protocols. A
- line going from a protocol to another protocol above or below it in the figure
- indicates that the upper protocol is a client of the lower protocol; that is,
- the upper protocol uses services provided by the lower protocol in order to
- carry out some functions.
-
- Note: The various AppleTalk protocols are sets of rules, not computer programs,
- and so can be implemented in many different ways on many different systems. All
- of the AppleTalk protocol functions that you can address or control from a
- Macintosh application are implemented as Macintosh device drivers or managers.
- Many other features of these protocols are implemented in software located only
- on internet routers that are not used to run general applications. Some parts of
- protocols are implemented by server software such as file servers and print
- servers. Therefore, when this chapter refers to a protocol as “doing” or
- “controlling” something, you should understand the statement to mean that some
- program that implements the protocol actually carries out the operation.
-
- ø 29.1 AppleTalk Protocols
-
- A link access protocol controls the access of the node to the network hardware,
- making it possible for many nodes to share the same communication hardware. Each
- link access protocol assigns a node ID to the node and decodes the node
- addresses of messages it receives. A link access protocol provides node-to-node
- delivery of data packets. Examples of link access protocols include the
- LocalTalk Link Access Protocol, the EtherTalk Link Access Protocol, and the
- TokenTalk Link Access Protocol.
-
- Whereas earlier implementations of AppleTalk were restricted to one 16-bit
- network number per cable (that is, one network number for all nodes connected
- with no intervening routers) and 254 nodes per network number, AppleTalk Phase 2
- allows more than one network number for each cable (other than LocalTalk, which
- is still limited to one network number on a cable). Each node in a network other
- than LocalTalk must be specified by both its 16-bit network number and its 8-bit
- node ID. In principle, each cable (other than LocalTalk) can now have over 16
- million (224) nodes. In any specific implementation, the hardware or software
- might limit the network to fewer nodes.
-
- Note: Before the introduction of AppleTalk Phase 2, AppleTalk allowed only one
- network number per cable (that is, one network number for all nodes connected
- with no intervening routers), and the term network was used to include all of
- the nodes connected by a single cable. Under AppleTalk Phase 2, however, more
- than one network number can be assigned to a single cable. The term network is
- now sometimes used to refer to the collection of all the nodes that share a
- single network number, and is sometimes used in the older sense to refer to all
- nodes connected with no intervening routers. In the latter case, you could say
- that a single network can have a range of network numbers. Because of this
- ambiguity, it is best to avoid using the term network without modifiers.
-
- The Datagram Delivery Protocol provides socket-to-socket delivery of data
- packets within an AppleTalk internet. A DDP packet’s address includes the socket
- number, node ID, and network number. Application-interface routines for DDP are
- described in “Datagram Delivery Protocol” in the AppleTalk Manager chapter of
- Volume II.
-
- The Routing Table Maintenance Protocol is used by routers on an AppleTalk
- internet to determine how to forward a data packet to the network number to
- which it is addressed. The RTMP implementation on a router maintains a table,
- called a routing table, that specifies the shortest path to each possible
- destination network number. The AppleTalk protocol software in a workstation
- contains only a small part of RTMP, called the RTMP stub, that DDP uses to
- determine the network number (or range of network numbers) of the network cable
- to which the node is connected and the network number and node ID of one router
- on that network cable. There is no application interface to the RTMP stub.
-
- The AppleTalk Transaction Protocol provides loss-free communications by
- retransmitting any data packets that are lost. Although—as you can see from
- Figure 29-1—the AppleTalk Manager provides high-level protocols that are clients
- of ATP, many applications use ATP directly to transmit data over an AppleTalk
- internet. The application interface to ATP is described in the AppleTalk Manager
- chapter of Volume II. There are some enhancements to ATP in AppleTalk Phase 2,
- described in “Changes to the .ATP Driver” later in this chapter.
-
- The Name-Binding Protocol maintains a table that contains the internet address
- and name of each entity in the node that is visible to other entities on the
- internet. The internet address includes the socket number, node ID, and network
- number. The name consists of three fields: the object, type, and zone. The
- object and type are assigned by the entity itself and can be anything the user
- or application assigns. A zone is a logical grouping of a subset of the nodes on
- the internet. The zone field of the name is the zone in which the node resides.
-
- NBP also allows its clients to obtain the internet address of any
- network-visible entity in the internet by providing its name. NBP maps this name
- to an internet address, thus providing the link between the user-supplied name
- for an entity and the internet address that is used by DDP to send and receive
- data packets. The application interface to NBP is described in the AppleTalk
- Manager chapter of Volume II. There is one enhancement to NBP in AppleTalk Phase
- 2, described in “A New NBP Wildcard Character” later in this chapter.
-
- The AppleTalk Echo Protocol listens for special packets sent by other nodes and,
- when it receives such a packet, echoes it back to the sender. The AEP is used by
- some clients of DDP to determine whether another node (known to have AEP) can be
- accessed over the internet, and to determine how long it takes a packet to reach
- another node. There is no application interface to AEP.
-
- The Zone Information Protocol maintains a table in each router, called the zone
- information table, that lists the relationships between zone names and networks.
- In AppleTalk Phase 2, a network (other than LocalTalk) can contain more than one
- zone or a zone can contain more than one network. You can use .XPP driver
- routines to obtain information from ZIP; these routines are discussed in
- “Obtaining Zone Information” later in this chapter.
-
- The AppleTalk Session Protocol sets up and maintains sessions between a
- workstation and a server. A session consists of a logical (as opposed to
- physical) connection between two entities on the internet. ASP is a
- nonsymmetrical protocol; that is, only one of the two entities involved in the
- session (the workstation) can send commands; the other entity (the server) is
- restricted to responding to the commands. ASP is used by the AppleTalk Filing
- Protocol, for example, to allow a user to manipulate files on a file server. As
- long as the session is open, the workstation can request directory information,
- change file names, and so forth. The file server must respond to the
- workstation’s commands and cannot initiate any actions on its own. ASP is
- discussed in the AppleTalk Manager chapter of Volume V.
-
- The AppleTalk Data Stream Protocol appears to its clients to maintain an open
- pipeline between two entities on the internet. Either entity can write a stream
- of bytes to the pipeline, or read data bytes from the pipeline. ADSP is a
- symmetrical protocol; that is, the two clients at either end of the connection
- are equal and can perform exactly the same operations. ADSP is especially useful
- for exchanging information between two equal entities, as in a telephone
- communication network, or for sending or receiving a continuous stream of data,
- as required by a terminal emulation program, for example. Because ADSP is a
- client of DDP, the data is actually sent as data packets, allowing ADSP to
- correct errors in transmission in a way that would not be possible for a true
- data stream connection. Thus, ADSP retains many of the advantages of a
- transaction-based protocol while providing to its clients a full-duplex data
- stream. ADSP is discussed in the sections “Using ADSP” and “.DSP Driver
- Functions” later in this chapter.
-
- The AppleTalk Filing Protocol provides an interface between an application and a
- file server. AFP is a client of ASP, and is used to access AppleShare file
- servers on Macintosh computer workstations. When the user opens a session with
- an AppleShare file server over an internet, it appears to any application
- running on the workstation that uses File Manager routines as if the files on
- the file server were located on a disk drive connected to the workstation. The
- application interface to AFP is described in the AppleTalk Manager chapter of
- Volume V.
- _______________________________________________________________________________
-
- æKY AppleTalk…Device…Drivers,…'adev'…Files,…and…the…LAP…Manager
- æC »AppleTalk Device Drivers, 'adev' Files, and the LAP Manager AppleTalk Manager
- _______________________________________________________________________________
-
- A protocol is only a set of rules, not a computer program. The various AppleTalk
- protocols are implemented as Macintosh device drivers, including
-
- • the .MPP driver, which implements LLAP, DDP, NBP, AEP, and the RTMP stub
- • the .ATP driver, which implements ATP
- • the .XPP driver, which implements ASP and the workstation portions of ZIP
- and AFP
- • the .DSP driver, which implements ADSP
- • the .ENET driver, which implements Ethertalk
-
- AppleTalk can also include one or more 'adev' files. An 'adev' file has file
- type 'adev' and contains a link access protocol implementation for a network
- (ELAP for Ethernet, for example). The LAP Manager makes it possible for the user
- to select among 'adev' files by using the Network control panel to control which
- network is used for the node’s AppleTalk connection. The 'adev' file and LAP
- Manager work together with the Network control panel (Network cdev) file. When
- the user selects a connection from the Network control panel, the LAP Manager
- routes AppleTalk communications through the selected link access protocol and
- hence through the selected hardware.
-
- The AppleTalk device drivers, LAP Manager, and 'adev' files are shown in Figure
- As you can see from the figure, each device driver implements one or more
- AppleTalk protocols.
-
- ø 29.2 AppleTalk Device Drivers
-
- Figure 29-3 shows the interfaces between a general application on a Macintosh
- computer being used as an AppleTalk workstation and the AppleTalk protocols, the
- LAP Manager, and the Ethernet hardware device driver. The lines connecting the
- application to the various components of AppleTalk indicate which components
- have application interfaces. As discussed in the preceding section, “AppleTalk
- Protocols,” each application interface is described at least in part in this or
- another volume of Inside Macintosh.
-
- ø 29.3 AppleTalk Application Interfaces.
-
- _______________________________________________________________________________
-
- æKY Using…the…AppleTalk…Manager…Vol…VI
- æC »USING THE APPLETALK MANAGER AppleTalk Manager
- _______________________________________________________________________________
-
- This section describes how to determine whether AppleTalk Phase 2 drivers are
- present and gives some advice on how to select the AppleTalk protocol that best
- servers your purposes. This section also describes how to use the features added
- to AppleTalk with Phase 2 and provides programming examples of the use of the
- .DSP driver and several other new AppleTalk features.
-
- _______________________________________________________________________________
-
- æKY Determining…Whether…AppleTalk…Phase…2…Drivers…Are…Present
- æC »Determining Whether AppleTalk Phase 2 Drivers Are Present AppleTalk Manager
- _______________________________________________________________________________
-
- Once the .MPP driver has been loaded into memory, you can use the Gestalt
- function to check the version of AppleTalk. The Gestalt function returns the
- version of the .MPP driver; if the version is greater than or equal to 53, then
- the .MPP driver supports AppleTalk Phase 2, and you can assume the other Phase 2
- drivers are present as well.
-
- Alternatively, you can call the SysEnvirons function as described in Chapter 1
- of Volume V. If the atDrvrVersNum field of the SysEnvRec record returned by this
- function is greater than or equal to 53, the .MPP driver supports AppleTalk
- Phase 2.
-
- _______________________________________________________________________________
-
- æKY Determining…Which…AppleTalk…Protocol…to…Use
- æC »Determining Which AppleTalk Protocol to Use AppleTalk Manager
- _______________________________________________________________________________
-
- AppleTalk offers a variety of communication protocols at a variety of levels.
- Your choice of protocol or protocols to use depends primarily on your needs, and
- can be influenced by your familiarity with network communications in general.
- You can write your own protocol handlers and call the low-level AppleTalk device
- drivers directly. However, if you are not communications expert and have no
- desire to design your own network protocols, you should probably use one of
- three AppleTalk protocols for sending and receiving data over the AppleTalk
- internet: the AppleTalk Transaction Protocol (ATP), the AppleTalk Session
- Protocol (ASP), or the AppleTalk Data Stream Protocol (ADSP).
-
- ATP is a lower-level protocol than ASP or ADSP. You cannot use ATP to establish
- a session and keep it open; rather, you request data from another socket or send
- a response (up to eight packets of data) from your socket to another socket that
- has requested data. You should use ATP if you want only to send a small amount
- of data and do not need the overhead required to maintain an open connection.
- ATP is described in the AppleTalk Manager chapters of Volume II and Volume V.
-
- ASP is designed to support a session between a server and one or more
- workstations. It is an asymmetrical protocol: all exchanges are initiated by a
- workstation and responded to by a server. The server cannot initiate an exchange
- of data except to send an attention message to a workstation, asking the
- workstation to request data from the server. An application running on a
- workstation must make calls to ASP to communicate with any server that uses ASP.
- If you want to develop a new type of asymmetrical, transaction-oriented server,
- you should consider using ASP to implement it. ASP is described in the AppleTalk
- Manager chapter of Volume V.
-
- ADSP is a symmetrical protocol that you can use to establish and maintain a
- connection between two equal entities. Either end of an ADSP connection can send
- data at any time. Although ADSP is a client of DDP, and therefore sends and
- receives data in packets (as do ATP and ASP), to an application using ADSP the
- data appears to be sent and received as a continuous stream. In addition to the
- duplex data stream maintained by an ADSP session, ADSP allows either end of a
- connection to send an attention message to the other end. You can use ADSP to
- establish two-way communication between computers, such as an interoffice party
- line or a terminal-emulation program. If you want to develop a server that
- requires two-way communication, you should consider using ADSP to implement it.
- ADSP is described in “Using ADSP” later in this chapter.
-
- _______________________________________________________________________________
-
- æKY The….MPP…Driver
- æC »THE .MPP DRIVER AppleTalk Manager
- _______________________________________________________________________________
-
- Within the AppleTalk Manager, the .MPP driver implements the Routing Table
- Maintenance Protocol (RTMP) stub, the Name Binding Protocol (NBP), the AppleTalk
- Echo Protocol (AEP), the Datagram Delivery Protocol (DDP), and the LocalTalk
- Link Access Protocol (LLAP). The AppleTalk Phase 2 version of the .MPP driver
- includes a new function that returns information about the .MPP driver,
- functions that send messages to routines in the AppleTalk Transition Queue, and
- a new wildcard character for NBP.
-
- _______________________________________________________________________________
-
- æKY Getting…Information…About…the….MPP…Driver
- æC »Getting Information About the .MPP Driver AppleTalk Manager
- _______________________________________________________________________________
-
- You can use the PGetAppleTalkInfo function to obtain information about the .MPP
- driver. In addition to the node ID and other information pointed to by the
- ABusVars global variable (discussed in the AppleTalk Manager chapter of Volume
- II), the PGetAppleTalkInfo function returns
-
- • a pointer to the .MPP driver’s device control entry data structure (DCE)
-
- • configuration flags, which indicate the status of certain conditions that
- are set at startup
-
- • a value (the selfSend flag) that indicates whether the node can send
- packets to itself
-
- • the network number range for the network to which the node is attached
-
- • the 8-bit node ID and 16-bit network number of the node
-
- • the 8-bit node ID and 16-bit network number of the last router from which
- the node has heard
-
- • the maximum capacities of the .MPP driver—such as the maximum number of
- protocol handlers and the maximum number of static sockets allowed by
- this driver
-
- • a pointer to the registered names queue
-
- • the node address of the node on the underlying data link (for example,
- the Ethernet hardware address)
-
- • the node’s zone name
-
- The data link address (for example, the Ethernet hardware address) and the zone
- name are returned only for extended networks; that is, network types that allow
- more than one network per cable. You must allocate memory for and provide
- pointers to the data buffers into which the PGetAppleTalkInfo function returns
- the data link address and zone name. You use the laLength parameter to specify
- the length of the data link address you want returned; the function returns the
- actual length of the data in the laLength parameter and returns the data in the
- buffer you provide.
-
- Note: Always use the PGetAppleTalkInfo function to obtain information about the
- .MPP driver. You can no longer rely on the validity of the global variables
- described in the AppleTalk chapter of Inside Macintosh, Volume II.
-
- FUNCTION PGetAppleTalkInfo (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always PGetAppleTalkInfo
- Æ 28 version word version of function
- ¨ 30 varsPtr pointer pointer to MPP globals
- ¨ 34 dcePtr pointer pointer to DCE for .MPP
- ¨ 38 portID word port number
- ¨ 40 configuration long configuration flags
- ¨ 44 selfSend word nonzero if self-send is enabled
- ¨ 46 netLo word low value of the network range
- ¨ 48 netHi word high value of the network range
- ¨ 50 ourAddr long local 24-bit AppleTalk address
- ¨ 54 routerAddr long 24-bit address of router
- ¨ 58 numOfPHs word max number of protocol handlers
- ¨ 60 numOfSkts word max number of static sockets
- ¨ 62 numNBPEs word max concurrent NBP requests
- ¨ 64 ntQueue pointer pointer to registered name queue
- ´ 68 laLength word length in bytes of data link address
- (extended networks only)
- Æ 70 linkAddr pointer pointer to data link address buffer
- (extended networks only)
- Æ 74 zoneName pointer pointer to zone name buffer
-
- The PGetAppleTalkInfo function returns information about the .MPP driver. If the
- node on which your program is running happens also to be running AppleTalk
- Internet Router software in the background, there may be more than one set of
- .MPP global variables in RAM. To make sure you are obtaining information about
- the .MPP driver that handles application software, always use the
- PGetAppleTalkInfo function rather than the Device Manager’s PBControl function.
- If you are using assembly language, or want to use the PBControl function, you
- must use a device driver reference number of –10 for the .MPP driver.
-
- Parameters
-
- ioResult
- The result of the function. When you execute the function asynchronously, the
- function sets this parameter to 1 and returns a function result of noErr as soon
- as the function begins execution. When the function completes execution, it sets
- the ioResult parameter to the actual result code.
-
- csCode
- Routine selector, automatically set by the MPW interface. Always equal to
- PGetAppleTalkInfo for this function.
-
- version
- The version number of the PGetAppleTalkInfo function you are calling. For
- version number 53 of the .MPP driver, this number is always 1.
-
- varsPtr
- A pointer to the MPP global variables. The MPP global variables are discussed in
- “Protocol Handlers and Socket Listeners” in Chapter 10 of Volume II.
-
- dcePtr
- A pointer to the device control entry (DCE) data structure for the .MPP driver.
- The DCE is described in the Device Manager chapters of Volumes II and V.
-
- portID
- The port number for the .MPP driver. The port number is always 0 unless you are
- requesting information for an .MPP driver being used by a router.
-
- configuration
- A 32-bit long word of configuration flags. The following flags are currently
- defined:
-
- Bit Flag Description
- 31 SrvAdrBit TRUE (1) if the routine that opened the .MPP driver requested a
- server node number. Server node numbers are described in the AppleTalk Manager
- of Volume V. This flag indicates only that the server-node number was requested,
- not that it was returned. Some AppleTalk devices, such as EtherTalk, do not
- honor a request for a server-node number.
-
- 30 RouterBit TRUE (1) if an AppleTalk Internet Router was loaded at system
- startup (that is, there's a router operating on the same node as your
- application). A router can be loaded but not active.
-
- 15 ExtendedBit TRUE (1) if the node is on an extended network.
-
- 7 BadZoneHintBit TRUE (1) if the zone name of the node you are on was not
- the same as the zone name stored in parameter RAM (sometimes referred to as the
- zone name hint) when the .MPP driver was opened. If the zone name hint is
- invalid, then the AppleTalk Manager uses the default zone for the network.
-
- 6 OneZoneBit TRUE (1) if only one zone is assigned to your extended network
- or if you are not on an extended network.
-
- selfSend
- This parameter is nonzero if the ability of a node to send packets to itself is
- enabled. Use the PSetSelfSend function, described in the AppleTalk Manager
- chapter of Volume V, to enable or disable this feature.
-
- netLo
- The low value of the range of network numbers on the local cable. Only extended
- networks can have a range of network numbers. For a nonextended network, this
- parameter returns the network number.
-
- netHi
- The high value of the range of network numbers on the local cable. Only extended
- networks can have a range of network numbers. For a nonextended network, this
- parameter returns the network number.
-
- ourAddr
- The 24-bit AppleTalk network address of the node you are on. The least
- significant byte of the longword is the node ID. The middle 16 bits are the
- network number. The most significant byte of the longword is reserved for use by
- Apple Computer, Inc.
-
- routerAddr
- The 24-bit AppleTalk network address of the last router from which your node
- heard traffic. The least significant byte of the longword is the node ID. The
- middle 16 bits are the network number. The most significant byte of the longword
- is reserved for use by Apple Computer, Inc. You should always use this address
- when you want to communicate with a router.
-
- numOfPHs
- The maximum number of protocol handlers that this .MPP driver allows.
-
- numOfSkts
- The maximum number of statically assigned sockets that this .MPP driver allows.
- Statically assigned sockets are described in Inside AppleTalk.
-
- numNBPEs
- The maximum number of concurrent requests to NBP that this .MPP driver allows.
-
- ntQueue
- A pointer to the first entry in the names table for the local node. You can use
- NBP routines to look up and register names in the names table. The names table
- is described in “Name-Binding Protocol” in Chapter 10 of Volume II.
-
- laLength
- When you call the PGetAppleTalkInfo function on a node on an extended network,
- you use this parameter to specify the number of bytes of the data link address
- the function should place in the buffer pointed to by the LinkAddr parameter. If
- you request more bytes than the total number of bytes in the address, then the
- function returns in the laLength parameter the actual number of bytes it placed
- in the buffer. If the address is longer than the size of the buffer, then the
- PGetAppleTalkInfo function fills the buffer and returns in the laLength
- parameter the actual length of the address, not the number of bytes returned.
- The function does not return an error when the buffer is too large or too small
- for the address.
-
- linkAddr
- A pointer to a buffer for the data link address returned for extended networks
- only. You use the laLength parameter to specify the number of bytes of the
- address that you want placed in this buffer. You must allocate a buffer large
- enough to hold the number of bytes you specify. Speficy NIL for this parameter
- if you do not want the function to provide a data-link address.
-
- zoneName
- A pointer to a buffer into which the PGetAppleTalkInfo function places the local
- node’s zone name. You must allocate a buffer of at least 33 bytes to hold this
- data, or specify NIL for the ZoneName parameter if you do not want to obtain the
- zone name. This field is returned only if the node is on an extended network.
-
- Result codes
- noErr 0 no error
- _______________________________________________________________________________
-
- æKY A…New…NBP…Wildcard…Character
- æC »A New NBP Wildcard Character AppleTalk Manager
- _______________________________________________________________________________
-
- The Name-Binding Protocol (NBP) allows the use of certain wildcard characters in
- AppleTalk names. You can use a wildcard character in a call to the PLookupName
- function, for example, to obtain names and addresses of all the entities in a
- given zone. NBP now supports the following wildcard characters:
-
- NBP Wildcard characters
-
- = All possible values. This character can be used alone instead of a name in
- the object or type fields.
-
- * This zone. This character can be used alone instead of the zone name for the
- local zone only.
-
- ≈ Any or no characters in this position. This character can be used to obtain
- matches for object or type fields. For example, pa≈l matches pal, paul,
- paper ball, and so forth. You can use only one double tilde (≈) character in
- any string. Press option-x to type the double tilde character on a Macintosh
- keyboard. If you use the double tilde character alone, it has the same
- meaning as the equal sign (=). Note that any node not running AppleTalk
- Phase 2 drivers will not recognize this character.
-
- _______________________________________________________________________________
-
- æKY The…LAP…Manager
- æC »THE LAP MANAGER AppleTalk Manager
- _______________________________________________________________________________
-
- The LAP Manager is a set of operating system utilities that provide a standard
- interface between the AppleTalk protocols and the various link access protocols,
- such as EtherTalk (ELAP), TokenTalk (TLAP), and LocalTalk (LLAP). Because the
- LAP Manager is running even when the .MPP driver is not open, the LAP Manager
- maintains the AppleTalk Transition Queue. The LAP Manager also contains protocol
- handlers for certain types of 802.2 packets. This section describes the
- AppleTalk Transition Queue and the LAP Manager 802.2 protocol handler, tells you
- how to add or remove an AppleTalk Transition Queue entry, and describes how to
- attach or detach your own 802.2 protocol handler.
-
- _______________________________________________________________________________
-
- æKY The…AppleTalk…Transition…Queue
- æC »The AppleTalk Transition Queue AppleTalk Manager
- _______________________________________________________________________________
-
- At any given time there might be two or more applications running that use
- AppleTalk. If one of these applications opens or closes the AppleTalk drivers,
- the other AppleTalk applications are affected. To ensure that your application
- is not adversely affected by such an event, your application can place an entry
- in the AppleTalk Transition Queue. The AppleTalk drivers send a message to each
- application that is listed in the AppleTalk Transition Queue each time a routine
-
- • opens the .MPP driver
- • closes the .MPP driver
- • indicates that it intends to close the .MPP driver
- • denies permission to close the .MPP driver
- • cancels its intention to close the .MPP driver
-
- Each of these events is referred to as an AppleTalk transition.
-
- Because opening or closing the .MPP driver opens or closes the .ATP and .XPP
- drivers as well, and bacause the .MPP driver must be open before an application
- can open the .DSP driver, knowing the status of the .MPP driver is tantamount to
- knowing the status of all AppleTalk drivers.
-
- Because the .MPP driver is not necessarily open when the AppleTalk Transition
- Queue must be called, the LAP Manager maintains the queue. Each entry in the
- AppleTalk Transition Queue is defined by the ATQentry record type.
-
- TYPE ATQentry = RECORD
- qLink: ATQentryPtr; {next queue entry}
- qType: INTEGER; {unused}
- CallAddr: ProcPtr; {pointer to your routine}
- END;
-
- ATQentryptr = ^ATQentry;
-
- When you want to add an entry to the AppleTalk Transition Queue, you must create
- an ATQentry record and give the LAP Manager a pointer to this record. The qLink
- field is a pointer to the next queue entry. You should set this field to NIL;
- the LAP Manager fills it in when an application adds another entry to the queue.
- The qType field is not used, but is present to maintain consistency with other
- operating system queues . The CallAddr field is a pointer to a routine that you
- provide. Your routine must handle the AppleTalk transition routines described in
- “How the AppleTalk Manager Calls Your AppleTalk Transition Queue Routine” later
- in this chapter.
-
- Because you allocate the memory for the AppleTalk Transition Queue entry, you
- can add as many fields to the end of the entry as you wish for your own
- purposes. Whenever your routine is called, the caller provides you with a
- pointer to the queue entry so that you can have access to the information you
- stored at the end of your queue entry.
-
- _______________________________________________________________________________
-
- æKY Adding…and…Removing…AppleTalk…Transition…Queue…Entries
- æC »Adding and Removing AppleTalk Transition Queue Entries AppleTalk Manager
- _______________________________________________________________________________
-
- There are three LAP Manager procedures you can use that are related to the
- AppleTalk Transition Queue:
-
- • The LAPAddATQ procedure adds an entry to the AppleTalk Transition Queue.
- You provide in the A0 register a pointer to an ATQentry record. The
- CallAddr field of the ATQentry record holds a pointer to your routine.
- The LAP Manager fills in the qLink field with a pointer to the next queue
- entry.
-
- • The LAPRmvATQ procedure removes an entry from the AppleTalk Transition
- Queue. You provide in the A0 register a pointer to your queue entry.
-
- • The LAPGetATQ procedure returns in the A1 register a pointer to the
- AppleTalk Transition Queue header.
-
- Assembly-language note: From assembly language, you call LAP Manager routines
- by placing a routine selector in the D0 register and executing a JSR instruction
- to an offset 2 bytes past the start of the LAP manager. Before you call the
- LAPAddATQ or LAPRmvATQ routines, you must also place a pointer to your AppleTalk
- Transition Queue entry in the A0 register. The LAPGetATQ routine returns a
- pointer to the AppleTalk Transition Queue header in the A1 register.
- Here is an assembly-language call to a LAP Manager routine:
-
- LAPMgrPtr EQU $B18 ;Entry point for LAP Manager
- LAPMgrCall EQU 2 ;Offset to LAP Manager routines
- ATQEntry EQU * ;AppleTalk Transition Queue entry
- ...
-
- MOVEQ #Code,D0 ;Place routine selector in D0
- MOVE.L LAPMgrPtr,An ;Put LAP Mgr entry pt in An
- MOVE.L ATQEntry,A0 ;Put ATQ entry in A0 (LAPAddATQ & LAPRmvATQ only)
- JSR LAPMgrCall(An) ;Jump to start of LAP Mgr routines
-
- You can use LAP Manager routines to add an entry to the AppleTalk Transition
- Queue, remove an entry from the queue, or obtain a pointer to the AppleTalk
- Transition Queue header. See “Using the AppleTalk Transition Queue,” earlier in
- this chapter, for a description of the queue and how to use it.
-
- PROCEDURE LAPAddATQ (entryPtr: pointer);
-
- On entry D0: 23
- A0: pointer to ATQentry record
-
- The LAPAddATQ procedure adds an entry to the AppleTalk Transition Queue. The
- entryPtr parameter is a pointer to an ATQentry record. The ATQentry record
- includes a pointer to the routine that AppleTalk calls when any routine opens or
- closes the .MPP driver, or indicates that it intends to close the .MPP driver.
- The ATQentry is described in “Using the AppleTalk Transition Queue” earlier in
- this chapter.
-
- PROCEDURE LAPRmvATQ (entryPtr: pointer);
- \
- On entry D0: 24
- A0: pointer to ATQentry record
-
- The LAPRmvATQ procedure removes an entry from the AppleTalk Transition Queue.
- The entryPtr parameter is a pointer to an ATQentry record.
-
- PROCEDURE LAPGetATQ (VAR eqPtr: pointer);
-
- On entry D0: 25
- On exit A1: pointer to AppleTalk Transition Queue header
-
- The LAPGetATQ procedure returns a pointer to the AppleTalk Transition Queue
- header.
- _______________________________________________________________________________
-
- æKY Sending…Messages…to…the…AppleTalk…Transition…Queue
- æC »Sending Messages to the AppleTalk Transition Queue AppleTalk Manager
- _______________________________________________________________________________
-
- Whereas it is unlikely that opening the .MPP driver will adversely affect
- another program, an application should never close the .MPP driver, because
- another program might be using it. Under certain circumstances, however, the
- system might close the .MPP driver, provided no application objects. The system
- uses the .MPP driver’s PATalkClosePrep function to inform each routine in the
- AppleTalk Transition Queue that it intends to close the .MPP driver, giving each
- routine in the queue the opportunity to deny permission to do so.
-
- The system provides a pointer to a 255-byte buffer when it calls the
- PATalkClosePrep function. If any routine in the AppleTalk Transition Queue
- denies permission to close the .MPP driver, it places a name in the buffer and
- returns control to the AppleTalk Manager. The name that the routine places in
- the buffer should be the name of the application that placed the entry in the
- queue. The PATalkClosePrep function then calls each routine in the AppleTalk
- Transition Queue a second time to inform it that the request to close the .MPP
- driver has been canceled. If any routine in the AppleTalk Transition Queue
- denies permission to close the .MPP driver, the PATalkClosePrep function returns
- the result code closeErr.
-
- If any routine denies permission to close the .MPP driver, the system displays a
- dialog box informing the user that another application is using the .MPP driver,
- and showing the name that the AppleTalk Transition Queue routine placed in the
- buffer. The dialog box gives the user the option of canceling the request to
- close AppleTalk, or of closing AppleTalk anyway.
-
- Note: If the user chooses to close AppleTalk despite the fact that an
- application is using it, the system calls the MPPClose function. AppleTalk calls
- each application in the AppleTalk Transition Queue again, this time informing it
- that AppleTalk is about to close. In this case, your AppleTalk Transition Queue
- routine must prepare for the imminent closing of AppleTalk; it cannot deny
- permission to the MPPClose function.
-
- FUNCTION PATalkClosePrep (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- Æ 26 csCode word always PATalkClosePrep
- Æ appName pointer buffer for name of application that denies request
-
- The PATalkClosePrep function calls each routine listed in the AppleTalk
- Transition Queue to request permission to close the .MPP driver.
- The routine that calls the PATalkClosePrep function must allocate a 255-byte
- buffer and provide a pointer to it in the appName parameter. If a routine in the
- AppleTalk Transition Queue denies permission to close the .MPP driver, that
- routine places a name in the buffer pointed to by the appName parameter, and the
- AppleTalk Manager calls each routine in the AppleTalk Transition Queue a second
- time to inform it that the request to close the .MPP driver has been canceled.
- The PATalkClosePrep function then returns the result code closeErr, indicating
- that the calling routine may not close the .MPP driver. The csCode parameter is
- a routine selector; it is always equal to PATalkClosePrep for this function.
-
- Result codes
- noErr 0 no error
- closeErr –24 permission to close .MPP driver was denied
-
- The system can use the PCancelATClosePrep function to undo the effects of the
- PATalkClosePrep function. The system uses this function, for example, if some
- condition prevents it from closing the .MPP driver even though each routine
- listed in the AppleTalk Transition Queue gave permission to close it. When the
- system calls the PCancelATClosePrep function, the AppleTalk Manager calls each
- routine in the AppleTalk Transition Queue to inform it that the request to close
- the .MPP driver has been canceled.
-
- FUNCTION PCancelATClosePrep (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- Æ 26 csCode word always PCancelATClosePrep
-
- The PCancelATClosePrep function undoes the effects of the PATalkClosePrep
- function. The PCancelATClosePrep function calls each routine in the AppleTalk
- Transition Queue to inform it that the request to close the .MPP driver has been
- canceled.
-
- The operating system uses this function, for example, if some condition prevents
- it from closing the .MPP driver even though each routine listed in the AppleTalk
- Transition Queue gave permission to close it.
-
- The csCode parameter is a routine selector, always equal to PCancelATClosePrep
- for this function.
-
- Result codes
- noErr 0 no error
- _______________________________________________________________________________
-
- æKY How…the…AppleTalk…Manager…Calls…Your…Transition…Queue…Routine
- æC »How the AppleTalk Manager Calls Your Transition Queue Routine AppleTalk Manager
- _______________________________________________________________________________
-
- When you have used the LAPAddATQ function to add an entry to the AppleTalk
- Transition Queue, the AppleTalk Manager calls your routine when any of the
- following AppleTalk transitions occurs:
-
- • A routine opens the .MPP driver.
- • A routine closes the .MPP driver.
- • A routine calls the ATalkClosePrep function.
- • One of the routines in the AppleTalk Transition Queue denies permission
- for the routine that called the ATalkClosePrep function to close
- AppleTalk, or a routine executes the PCancelATClosePrep function.
-
- When the AppleTalk Manager calls your AppleTalk Transition Queue routine, the
- first item on the stack (after the return address) is a routine selector. There
- is one routine selector for each type of transition:
-
- Routine selector Transition
- 0 .MPP driver opened
- 2 .MPP driver about to close
- 3 ATalkClosePrep function has been called
- 4 Closing of .MPP driver has been canceled
-
- The interface between the AppleTalk Transition Queue and your routine follows
- the conventions of the C language: Your routine must preserve all registers
- except D0, D1, D2, A0 and A1; all parameters are passed on the stack as long
- words.
-
- Note: Because the number of parameters that an AppleTalk Transition Queue
- routine must read off the stack varies with the routine selector, and because
- the routine must be able to place a value in the D0 register, you cannot use
- Pascal to write an AppleTalk Transition Queue routine.
-
- When an application calls the MPPOpen function to open the .MPP driver, the
- AppleTalk Manager calls every routine listed in the AppleTalk Transition Queue
- after it opens the .MPP driver. When the AppleTalk Manager calls your AppleTalk
- Transition Queue routine to tell it that the .MPP driver has been opened, the
- stack looks like this:
-
- SP Æ Return address (4 bytes)
- Routine selector; 0 when .MPP opens (4 bytes)
- Pointer to AppleTalk Transition Queue entry (4 bytes)
- Pointer to Device Manager’s parameter block (4 bytes)
- previous contents
-
- If the .MPP driver is already open and a routine executes the MPPOpen function,
- the AppleTalk Manager does not call the routines in the AppleTalk Transition
- Queue.
-
- You can use the pointer to your routine’s entry in the AppleTalk Transition
- Queue to get access to any fields at the end of the queue entry that you
- allocated for your own use. The last item on the stack is a pointer to the start
- of the Device Manager extended parameter block used by the routine that opened
- the .MPP driver. This pointer is provided for your information only; you must
- not change any of the fields in this parameter block.
-
- Your AppleTalk Transition Queue routine can perform any tasks you wish in
- response to the notification that the .MPP driver has been opened, such as using
- NBP to register a name on the internet.
-
- When any routine calls the MPPClose function to close the .MPP driver, the
- AppleTalk Manager calls every routine listed in the AppleTalk Transition Queue
- before the .MPP driver closes. When the AppleTalk Manager calls your routine to
- tell it that the .MPP driver is about to close, the stack looks like this:
-
-
- SP Æ Return address (4 bytes)
- Routine selector; 2 when .MPP is about to close (4 bytes)
- Pointer to AppleTalk Transition Queue entry (4 bytes)
- previous contents
-
- If the .MPP driver is already closed and a routine executes the MPPClose
- function, the AppleTalk Manager does not call the routines in the AppleTalk
- Transition Queue.
-
- You can use the pointer to your routine’s entry in the AppleTalk Transition
- Queue to get access to any fields at the end of the queue entry that you
- allocated for your own use.
-
- Your routine can perform any tasks you wish to prepare for the imminent closing
- of AppleTalk, such as ending a session with a remote terminal and informing the
- user that the connection is being closed. You must return control to the
- AppleTalk Manager as quickly as possible. When the AppleTalk Manager calls your
- routine with a routine selector of 2, you cannot prevent the .MPP driver from
- closing.
-
- When a routine calls the ATalkClosePrep function to inform the AppleTalk Manager
- that it wants to close the .MPP driver, the AppleTalk Manager calls every
- routine listed in the AppleTalk Transition Queue to request permission to close
- the .MPP driver. When the AppleTalk Manager calls your routine to request
- permission to close the .MPP driver, the stack looks like this:
-
-
- SP Æ Return address (4 bytes)
- Routine selector; 3 to ask permission to close .MPP (4 bytes)
- Pointer to AppleTalk Transition Queue entry (4 bytes)
- Pointer to pointer to name of client (4 bytes)
- previous contents
-
- Your routine can return either a longword of zeros in the D0 register,
- indicating that it accepts the request to close, or a nonzero value in the D0
- register, indicating that it denies the request to close.
- You can use the pointer to your routine’s entry in the AppleTalk Transition
- Queue to get access to any fields at the end of the queue entry that you
- allocated for your own use.
-
- The last parameter on the stack is a pointer to the clientName field (offset 28)
- in the .MPP driver parameter block that was used by the routine that called the
- PATalkClosePrep function. This field contains a pointer to a 255-byte buffer. If
- you intend to deny the request to close AppleTalk, you should place a string in
- this buffer containing the name of your application. The routine that called the
- PATalkClosePrep function can then display a dialog box telling the user the name
- of the application that is currently using AppleTalk.
-
- Because the AppleTalk Manager calls your routine again (with the routine
- selector set to 2) before the .MPP driver actually closes, it is not necessary
- for your routine to do anything other than grant or deny permission in response
- to being called with the routine selector set to 3. However, you might want to
- prohibit the users from opening new sessions or establishing new connections
- while you are waiting for the .MPP driver to close.
-
- When a routine calls the PCancelATClosePrep function to cancel the effects of
- the PATalkClosePrep function, or when any routine in the AppleTalk Transition
- Queue denies permission for the .MPP driver to close, the AppleTalk Manager
- calls every routine listed in the AppleTalk Transition Queue to inform it that
- the request to close the .MPP driver has been canceled. When the AppleTalk
- Manager calls your AppleTalk Transition Queue routine to cancel a request to
- close the .MPP driver, the stack looks like this:
-
-
- SP Æ Return address (4 bytes)
- Routine selector; 4 to cancel a close (4 bytes)
- Pointer to AppleTalk Transition Queue entry (4 bytes)
- previous contents
-
- You can use the pointer to your routine’s entry in the AppleTalk Transition
- Queue to get access to any fields at the end of the queue entry that you
- allocated for your own use.
-
- If your routine performed any tasks to prepare for the closing of AppleTalk, it
- should reverse their effects when it is called with the routine selector set to
- 4.
-
- Listing 29-1 illustrates the use of the AppleTalk Transition Queue. It defines a
- routine that AppleTalk is to call when an AppleTalk transition occurs. This
- routine first checks the stack to determine why it is being called, and then
- acts accordingly. If the routine selector indicates that the .MPP driver has
- just opened, the listing uses NBP to register a name on the internet. If the
- .MPP driver is about to close, the routine calls ADSP to close the session and
- displays a dialog box informing the user that the session is being closed. If
- some application is asking permission to close the .MPP driver, the routine
- checks to see if your application has an open ADSP session. If your application
- has a current open ADSP session, the routine places the name of your application
- in the buffer provided by the client that called the PATalkClosePrep function,
- and places a 0 in the D0 register. If your application has no open ADSP session,
- the routine places a 1 in the D0 register. If AppleTalk is canceling a request
- to close the .MPP driver, the routine terminates without further action.
- Listing 29-1 also defines an entry to the AppleTalk Transition Queue that points
- to the routine, and calls the LAPAddATQ procedure to add this entry to the
- queue.
-
- Listing 29-1. Using the AppleTalk Transition Queue (TO BE PROVIDED)
-
- _______________________________________________________________________________
-
- æKY The…LAP…Manager…802.2…Protocol
- æC »The LAP Manager 802.2 Protocol AppleTalk Manager
- _______________________________________________________________________________
-
- The Institute of Electrical and Electronics Engineers (IEEE) has defined a
- series of communication protocols for use on a variety of networks. At the
- hardware and signaling level, these protocols include the 802.3 Ethernet
- protocol, the 802.4 Token Bus protocol, and the 802.5 Token Ring protocol. At
- the link access level, these protocols are all handled by another IEEE protocol,
- the 802.2 protocol. The AppleTalk LAP Manager includes two routines that allow
- you to attach and detach protocol handlers for 802.2 Type 1 data packets: the
- L802Attach and L802Detach routines. You can write an application that reads
- 802.2 Type 1 data packets, and use the L802Attach routine to install your
- application as a client of the LAP Manager. The ANSI/IEEE standards for the 802
- protocols are published by the Institute of Electrical and Electronics
- Engineers.
-
- The first 14 bytes of a packet sent or received by the .ENET driver are the
- header. The first 12 bytes consist of the destination and source data link
- addresses (such as the Ethernet hardware addresses). If the value of the last
- two bytes in the header is greater than 1500, then the .ENET driver treats that
- field as an Ethernet protocol type discriminator. See “The .ENET Driver,” later
- in this chapter, for more information on Ethernet protocols. If the value of the
- last two bytes in the header is less than 1500, then the packet is an 802.3
- protocol packet and the .ENET driver passes it to the LAP Manager.
-
- The LAP Manager receives the entire 802.3 packet from the .ENET driver. The
- first three bytes of the 802.3 data constitues the header for the 802.2
- protocol. The first byte of the 802.2 header is known as the destination service
- access point (DSAP). If the DSAP type field is equal to $AA, then the first five
- bytes of the 802.2 data constitutes a protocol discriminator known as the
- subnetwork access protocol (SNAP) type. If the SNAP type field is $00000080F3,
- indicating the AppleTalk Address Resolution Protocol (AARP), then the next four
- bytes of the 802.2 data constitutes a third type field, the AARP packet type.
- AARP is discussed in Inside AppleTalk.
-
- The following data packet header, for example, indicates an Ethernet packet
- containing AppleTalk data. The .ENET driver would deliver this packet to the
- AppleTalk Phase 1 device drivers.
-
- 02608C010203 02608C040506 809B
-
- By contrast, the following data packet header indicates an 802.3 packet
- containing AppleTalk data. The .ENET driver would deliver this packet to the
- AppleTalk Phase 2 LAP Manager
-
- 02608C010203 02608C040506 0060 AA AA 03 080007809B
-
- Similarly, the following data packet header indicates an 802.3 packet to be
- delivered to the EtherTalk AARP handler:
-
- 02608C010203 02608C040506 0060 AA AA 03 00000080F3 0001809B
-
- When you call the L802Attach function, you provide a pointer to your protocol
- handler, the reference number of the .ENET driver, and a pointer to a string
- containing one or more type fields. The type fields indicate the DSAP value and
- any other protocol type fields (such as the SNAP type and the AARP type). The
- LAP Manager delivers to your protocol handler any 802.2 data packets that have
- the protocol type you specify.
- _______________________________________________________________________________
-
- æKY Attaching…and…Detaching…802.2…Protocol…Handlers
- æC »Attaching and Detaching 802.2 Protocol Handlers AppleTalk Manager
- _______________________________________________________________________________
-
- You can attach to the LAP Manager your own protocol handler for 802.2 protocols.
- The LAP Manager has permanent handlers for certain types of EtherTalk packets.
- You cannot replace or override the permanent LAP Manager protocol handlers.
-
- FUNCTION L802Attach (Eref: word; handlerPtr: procptr; ProtType: pointer) :
- OSErr;
-
-
- On entry D0: 21
- D2: reference number of .ENET driver
- A0: pointer to your protocol handler
- A1: pointer to protocol specification
-
- On exit D0: nonzero if error
-
- The L802Attach function attaches to the LAP Manager a protocol handler for a
- specific IEEE 802.2 protocol type.
-
- The Eref parameter is the reference number of the .ENET driver that was returned
- by the OpenSlot function when you or somone else opened the .ENET driver. If you
- are not using the .ENET driver or a driver that uses the same interface as the
- .ENET driver, you cannot use the L802Attach function. The handlerPtr parameter
- is a pointer to your protocol handler.
-
- The ProtType parameter is a pointer to the protocol type specification for this
- protocol handler. The protocol type specification consists of one or more
- protocol type fields, each preceded by a length byte. The LAP Manager reads the
- protocol type fields in the 802.2 data packet header to determine to which
- protocol handler (if any) to deliver the packet. The first type field in your
- protocol specification is 1 byte long and is known as the destination service
- access point (DSAP). If the DSAP type field is equal to $AA, then the protocol
- type specification can contain a second type field, the 5-byte subnetwork access
- protocol (SNAP) type. If the SNAP type field is $00000080F3, indicating the
- AppleTalk Address Resolution Protocol (AARP), then the protocol type
- specification can contain a third type field, the 4-byte AARP protocol type.
- Terminate the list of protocol type fields with a byte of zeros.
-
- The following protocol type specification, for example, indicates an 802.3
- packet containing AppleTalk data. The .ENET driver would deliver this packet to
- the AppleTalk Phase 2 LAP Manager. The first byte, $01, is the length byte for
- the first protocol type field (the DSAP type field), $AA. The third byte, $05,
- is the length byte for the next protocol type field, the SNAP. The final byte
- ($00) terminates the type specification.
-
- 01 AA 05 08 00 07 80 9B 00
-
- The following protocol type specification indicates an 802.3 packet to be
- delivered to the EtherTalk AARP handler: Notice that the SNAP field is followed
- by an additional type field, the AARP protocol type.
-
- 01 AA 05 00 00 00 80 F3 04 00 01 80 9B 00
-
- See the ANSI/IEEE standard 802.2 for more information about 802.2 protocols, and
- Inside AppleTalk for more information about AARP.
-
- Result codes
- noErr 0 no error
-
- FUNCTION L802Detach (Eref: word; ProtType: pointer) : OSErr;
-
- On entry D0: 22
- D2: reference number of .ENET driver
- A1: pointer to protocol specification
-
- On exit D0: nonzero if error
-
- The L802Detach function detaches from the LAP Manager a protocol handler for a
- specific IEEE 802.2 protocol type.
-
- The Eref parameter is the reference number of the .ENET driver that was returned
- by the OpenSlot function when you or somone else opened the .ENET driver. The
- handlerPtr parameter is a pointer to your protocol handler.
-
- The ProtType parameter is a pointer to the protocol type specification for this
- protocol handler. You must specify exactly the same protocol type as you
- specified for the L802Attach function when you attached the protocol handler.
-
- Result codes
- noErr 0 no error
- _______________________________________________________________________________
-
- æKY AppleTalk…Data…Stream…Protocol…(ADSP)
- æC »APPLETALK DATA STREAM PROTOCOL (ADSP) AppleTalk Manager
- _______________________________________________________________________________
-
- One of the significant new features of AppleTalk introduced with AppleTalk Phase
- 2 is the AppleTalk Data Stream Protocol (ADSP), which provides a full-duplex
- data stream connection between two nodes in the AppleTalk internet. Like the
- AppleTalk Session Protocol, Printer Access Protocol, and AppleTalk Transaction
- Protocol, ADSP uses the Datagram Delivery Protocol to send its data over the
- internet. Therefore, even though ADSP appears to its clients to handle data as a
- stream of bytes, the data is actually transmitted and received by DDP in
- packets. ADSP takes advantage of this fact by including control and status
- information in the DDP packet header. You can use the .DSP driver functions
- described in “.DSP Driver Functions,” later in this chapter, to control an ADSP
- connection. The
- .DSP driver takes care of implementation of the ADSP protocol for you. To use
- ADSP, you must have the file named 'ADSP' in your system folder.
-
- Every ADSP connection is between two sockets in the AppleTalk internet. Each
- socket can establish simultaneous ADSP connections with several other sockets,
- but there can be only one ADSP connection between any two sockets at one time.
- When a pair of sockets establishes an ADSP connection, each socket client
- initializes and maintains a certain amount of control and state information that
- it uses for error checking and to synchronize communication with the other
- socket client.
-
- The combination of a socket and the ADSP information maintained by the socket
- client is referred to as a connection end. When two connection ends establish
- communication, the connection is considered an open connection. When both
- connection ends terminate the link and dispose of the connection information
- each maintains, the connection is considered a closed connection. If one
- connection end is established but the other connection end is unreachable or has
- disposed of its connection information, the connection is considered a half-open
- connection. No communication can occur over a half-open or closed connection. To
- prevent a half-open connection from tying up resources, ADSP automatically
- closes any half-open connection that cannot reestablish communications within
- two minutes.
-
- _______________________________________________________________________________
-
- æKY Using…ADSP
- æC »Using ADSP AppleTalk Manager
- _______________________________________________________________________________
-
- You can use the AppleTalk Data Stream Protocol to implement a data stream
- connection between any two sockets on the internet. (Note that although there
- can be only one ADSP connection between any two sockets, a single socket can
- maintain connections with several other sockets.) This section describes how to
- open, maintain, and close a connection between two sockets on an internet. It
- also describes how to establish and use a connection listener; that is, a
- connection end that waits passively to receive a connection request and then
- passes the connection request on to its client, the connection server. Finally,
- this section describes how to write a routine that ADSP calls when your
- connection end receives an unsolicited connection event.
- _______________________________________________________________________________
-
- æKY The…ADSP…Connection…Control…Block
- æC »The ADSP Connection Control Block AppleTalk Manager
- _______________________________________________________________________________
-
- When you establish an ADSP connection end, you must allocate a nonrelocatiable
- block of memory for, and provide a pointer to, a data structure known as a
- connection control block (CCB). The CCB is used by ADSP to store state
- information about the connection end. You may read the fields in the CCB to
- obtain information about the connection end, but you are not allowed to write to
- any of the fields except one, the userFlags field. The connection control block
- requires 242 bytes, and is defined by the TRCCB record.
-
- TPCCB = ^TRCCB;
-
- TRCCB = PACKED RECORD
- ccbLink: TPCCB; {link to next CCB}
- refNum: INTEGER; {user reference number}
- state: INTEGER; {state of the connection end}
- userFlags: Byte; {user flags for connection}
- localSocket: Byte; {local socket number}
- remoteAddress: AddrBlock; {remote end internet address}
- attnCode: INTEGER; {attention code received}
- attnSize: INTEGER; {size of attention data}
- attnPtr: Ptr; {pointer to attention data}
- reserved: PACKED ARRAY [1..220] OF Byte {reserved for use by ADSP}
- END;
-
- The internet address of the remote connection end is defined in the TRCCB record
- by an AddrBlock record:
-
- AddrBlock = PACKED RECORD
- aNet: INTEGER; {network number}
- aNode: Byte; {node ID}
- aSocket: Byte; {socket number}
- END;
-
- Field descriptions
-
- ccbLink
- Pointer to the next CCB. For use by ADSP only.
-
- refnum
- The reference number of the connection end. This number is assigned by ADSP when
- you establish the connection end.
-
- state
- The state of the connection end, as follows:
-
- State Value Meaning
- sListening 1 Socket is a connection listening socket; that is, a socket
- that accepts ADSP requests to open connections and passes them on to a socket
- client. Ordinarily used only by servers.
-
- sPassive 2 Socket client is inactive but capable of accepting an ADSP
- request to open a connection. Unlike a connection listening socket, which passes
- the open-connection request on to a routine that can establish the connection on
- any socket, a socket client in the sPassive state can accept an open-connection
- request only to establish itself as a connection end.
-
- sOpening 3 Socket client has sent an open-connection request and is waiting
- for acknowledgment.
-
- sOpen 4 Connection is open.
-
- sClosing 5 Socket client has requested that ADSP close the connection, and
- ADSP is sending data or waiting for acknowledgement of data it has sent before
- closing the connection.
-
- sClosed 6 Either connection end or ADSP has closed the connection.
-
- userFlags
- Flags that indicate an unsolicited connection event has occurred. An unsolicited
- connection event is an event initiated by ADSP or the remote connection end that
- is not in response to any .DSP function that you executed.
-
- Each time an unsolicited connection event occurs, ADSP sets a flag in the
- userFlags field of the CCB and calls the routine you specified in the
- userRoutine parameter to the dspInit command (if any). The user routine must
- read the userFlags field and then clear the flag to 0. ADSP cannot notify your
- routine of future events unless you clear the flag after each event.
-
-
- ADSP recognizes four types of unsolicited connection events, one corresponding
- to each of the flags in this field. The events and flags are defined as follows,
- where bit 7 is the most significant bit:
-
- Event Flag Bit Meaning
- eClosed 7 ADSP has been informed by the remote connection end that the
- remote connection end has closed the connection.
-
- eTearDown 6 ADSP has determined that the remote connection end is not
- responding, and so has closed the connection.
-
- eAttention 5 ADSP has received an attention message from the remote
- connection end.
-
- eFwdReset 4 ADSP has received a forward reset command from the remote
- client end, has discarded all ADSP data not yet delivered— including the data in
- the local client end’s receive queue—and has resynchronized the connection.
-
- none 3–0 Reserved
-
- localSocket
- The socket number through which DDP transmits and receives the ADSP packets.
-
- remoteAddress
- The internet address of the socket used by the remote connection end.
-
- attnCode
- The attention code received by ADSP when the remote connection end sends an
- attention message.
-
- attnSize
- The size of the attention message received by ADSP when the remote connection
- end sends an attention message.
-
- attnPtr
- A pointer to a buffer containing the attention message received by ADSP from the
- remote connection end.
-
- reserved
- A data buffer reserved for use by ADSP.
-
- _______________________________________________________________________________
-
- æKY The….DSP…Parameter…Block
- æC »The .DSP Parameter Block AppleTalk Manager
- _______________________________________________________________________________
-
- The .DSP commands use the AppleTalk preferred interface. Each .DSP command
- includes a pointer to a parameter block that includes all of the parameters
- needed by that command.
-
- The .DSP parameter block is defined by the DSPParamBlock record.
-
- DSPParamBlock = PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: INTEGER; {queue type}
- ioTrap: INTEGER; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OsErr; {result code}
- ioNamePtr: StringPtr; {used only for Open routine}
- ioVRefNum: INTEGER; {volume reference number}
- ioCRefNum: INTEGER; {driver reference number}
- csCode: INTEGER; {primary command code}
- qStatus: LONGINT; {reserved for ADSP}
- ccbRefNum: INTEGER; {CCB reference number}
-
- CASE INTEGER OF
- dspInit,
- dspCLInit:
- (
- ccbPtr: TPCCB; {pointer to CCB}
- userRoutine: ProcPtr; {pointer to user routine}
- sendQSize: INTEGER; {size of send queue}
- sendQueue: Ptr; {pointer to send queue}
- recvQSize: INTEGER; {size of receive queue}
- recvQueue: Ptr; {pointer to receive queue}
- attnPtr: Ptr; {pointer to attention-message buffer}
- localSocket: Byte; {local socket number}
- );
-
- dspOpen,
- dspCLListen,
- dspCLDeny:
- (
- localCID: INTEGER; {local connection ID}
- remoteCID: INTEGER; {remote connection ID}
- remoteAddress: AddrBlock; {remote internet address}
- filterAddress: AddrBlock; {address filter}
- sendSeq: LONGINT; {send sequence number}
- sendWindow: INTEGER; {size of remote buffer}
- recvSeq: LONGINT; {receive sequence number}
- attnSendSeq: LONGINT; {attention send seq number}
- attnRecvSeq: LONGINT; {attention receive seq num}
- ocMode: Byte; {connection opening mode}
- ocInterval: Byte; {interval bet open requests}
- ocMaximum:Byte;{retries of open conn req}
- );
-
- dspClose,
- dspRemove:
- (
- abort: Byte; {abort send requests}
- );
-
- dspStatus:
- (
- statusCCB: TPCCB; {pointer to CCB}
- sendQPending: INTEGER; {bytes waiting in send queue}
- sendQFree: INTEGER; {available send-queue buffer}
- recvQPending: INTEGER; {bytes in receive queue}
- recvQFree: INTEGER; {avail receive-queue buffer}
- )
-
- dspRead,
- dspWrite:
- (
- reqCount: INTEGER; {requested number of bytes}
- actCount: INTEGER; {actual number of bytes}
- dataPtr: Ptr; {pointer to data buffer}
- eom: Byte; {1 if end of message}
- flush: Byte; {1 to send data now}
- )
-
- dspAttention:
- (
- attnCode: INTEGER; {client attention code}
- attnSize: INTEGER; {size of attention data}
- attnData: Ptr; {pointer to attention data}
- attnInterval: Byte; {reserved}
- )
-
- dspOptions:
- (
- sendBlocking: INTEGER; {send-blocking threshold}
- sendTimer: Byte; {reserved}
- rtmtTimer: Byte; {reserved}
- badSeqMax: Byte; {retransmit advice threshold}
- useCheckSum: Byte; {DDP checksum for packets}
- )
-
- dspNewCID:
- (
- newCID: INTEGER; {new connection ID}
- )
- END;
-
- The qLink, qType, ioTrap, ioCmdAddr, ioNamePtr, and ioVRefNum fields are filled
- in by the Device Manager; your application should not have to set or read these
- parameters. The ioResult parameter returns the result of the function; in the
- case that you call the function asynchronously, the Device Manager sets this
- field to 1 as soon as you call the function, and changes the field to the actual
- result code when the function completes execution. The ioCompletion parameter is
- a pointer to a completion routine that you can provide; the Device Manager calls
- your completion routine when it completes execution of the PBControl function.
- If you are not providing a completion routine, specify NIL for this field. The
- ioCRefNum and csCode fields specify the driver and the command to be executed;
- you must fill in the csCode field.
-
- The qStatus field is reserved for use by ADSP. The ccbRefNum field is a
- reference number for the connection control block. The CCB reference number is
- returned by ADSP in response to the dspInit command. You must specify this
- number as a parameter to every .DSP driver routine you call subsequently.
-
- The remaining parameters are used only for specific commands; each of these
- parameters is described in “.DSP Driver Commands” later in this chapter.
-
- _______________________________________________________________________________
-
- æKY Opening…and…Maintaining…an…ADSP…Connection
- æC »Opening and Maintaining an ADSP Connection AppleTalk Manager
- _______________________________________________________________________________
-
- To use ADSP to establish and maintain a connection between a socket on your
- local node and a remote socket, use the following procedure:
-
- 1. Use the MPPOpen command to open the .MPP driver and then use the OpenDriver
- command to open the .DSP driver. The OpenDriver routine returns the reference
- number for the .DSP driver; you must supply this reference number each time you
- call the .DSP driver.
-
- 2. Allocate nonrelocatable memory for a connection control block, send and
- receive queues, and an attention message buffer. If you need to allocate the
- memory dynamically while the program is running, use the NewPtr routine.
- Otherwise, the way in which you allocate the memory depends on the compiler you
- are using (the program listing at the end of this section shows how it’s done in
- Pascal). The memory that you allocate becomes the property of ADSP when you call
- the dspInit command to establish a connection end. You cannot write any data to
- this memory except by calling ADSP, and you must ensure that the memory remains
- locked until you call the dspRemove command to eliminate the connection end.
-
- The connection control block is 242 bytes. The attention message buffer must be
- 570 bytes. When you send bytes to a remote connection end, ADSP stores the bytes
- in a buffer called the send queue. It keeps the bytes you sent in the send queue
- until the remote connection end acknowledges their receipt, so that they are
- available to be retransmitted if necessary. When the local connection end
- receives bytes, it stores them in a buffer called the receive queue until you
- read them. The sizes you need for the send and receive queues depend on the
- lengths of the messages being sent.
-
- ADSP does not transmit data from the remote connection end until there is room
- for it in your receive queue. If your send or receive queues are too small, they
- limit the speed with which you can transmit and receive data. A queue size of
- 600 bytes should work well for most applications. If you are using ADSP to send
- a continuous flow of data, a larger data buffer will improve performance. If
- your application is sending or receiving the user’s keystrokes, a smaller buffer
- should be adequate. The constant minDSPQueueSize indicates the minimum queue
- size that you can use.
-
- If you are using a version of the .DSP driver prior to version 1.5, you must
- allocate send and receive queues that are 12% larger than the actual buffer
- sizes you need, to provide some extra space for use by the .DSP driver. Version
- 1.5 and later versions of the .DSP driver use a much smaller, and variable,
- portion of buffer space for overhead.
-
- 3. Use the dspInit command to establish a connection end. You must provide
- pointers to the connection control block, send buffer, receive buffer, and
- attention message buffer. You may also provide a pointer to the user routine
- that ADSP calls when your connection end receives an unsolicited connection
- event. User routines are discussed in “Writing a User Routine For Connection
- Events” later in this chapter.
-
- If there is a specific socket that you want to use for the connection end, you
- can specify the socket number in the localSocket parameter. If you want ADSP to
- assign the socket for you, specify 0 for the localSocket parameter. ADSP returns
- the socket number when the dspInit command completes execution.
-
- 4. If you wish to do so, you can use the NBPRegister function to add the name
- and address of your connection end to the node’s names table. The NBPRegister
- function is described in the AppleTalk Manager chapter of Volume II.
-
- 5. You can use the dspOptions command to set several parameters that control
- the behavior of the connection end. Because every parameter has a default value,
- the use of the dspOptions command is optional. You can specify values for the
- following parameters:
-
- • The sendBlocking parameter, which sets the maximum number of bytes that
- may accumulate in the send buffer before ADSP sends a packet to the
- remote connection end. You can experiment with different values of the
- sendBlocking parameter to determine which provides the best performance;
- the default value of 16 bytes gives good performance under most
- circumstances.
-
- • The badSeqMax parameter, which sets the maximum number of out-of-sequence
- data packets that the local connection end can receive before requesting
- the remote connection end to retransmit the missing data. Under most
- circumstances, the default value of 3 provides good performance.
-
- • The useCheckSum parameter, which determines whether DDP should compute a
- checksum and include it in each packet that it sends to the remote
- connection end. Using checksums slows communications slightly. Normally
- ADSP and DDP perform enough error checking to ensure safe delivery of all
- data; set the useCheckSum parameter to 1 only if you feel that the
- network is highly unreliable.
-
- 6. Call the dspOpen command to open the connection. The dspOpen command has
- four possible modes of operation: ocAccept, ocEstablish, ocRequest, and
- ocPassive. Normally you use either the ocRequest or ocPassive mode. You must
- specify one of these four modes for the ocMode parameter when you call the
- dspOpen command.
-
- The ocAccept mode is used only by connection servers. The ocEstablish mode is
- used by routines that determine their connection-opening parameters and
- establish a connection independently of ADSP, but use ADSP to transmit and
- receive data.
-
- Use the ocRequest mode when you want to establish communications with a specific
- socket on the internet. When you execute the dspOpen command in the ocRequest
- mode, ADSP sends an open-connection request to the address you specify.
-
- If the socket to which you send the open-connection request is a connection
- listener, the connection server that operates that connection listener can
- choose any socket on the internet to be the connection end that responds to the
- open-connection request. To restrict the socket from which you will accept a
- response to your open-connection request, specify a value for the filterAddress
- parameter to the dspOpen command. When your connection end receives a response
- from a socket that meets the restrictions of the filterAddress parameter, it
- acknowledges the response and ADSP completes the connection.
-
- To use the ocRequest mode, you must know the complete internet address of the
- remote socket, and the ADSP client at that address must either be a connection
- listener or have executed the dspOpen command in the ocPassive mode. You can use
- the NBPLookup function to obtain a list of names of objects on the internet and
- to determine the internet address of a socket when you know its name. The
- NBPLookup function is described in the AppleTalk Manager chapter of Volume II.
- Enhancements to the wildcard-lookup feature of NBP are discussed in “A New NBP
- Wildcard Character” earlier in this chapter.
-
- Use the ocPassive mode when you expect to receive an open-connection request
- from a remote socket. You can specify a value for the filterAddress parameter to
- restrict the network number, node ID, or socket number from which you will
- accept an open-connection request. When your connection end receives an
- open-connection request that meets the restrictions of the filterAddress
- parameter, it acknowledges the request and ADSP completes the connection.
-
- You can poll the state field in the connection control block to determine when
- the connection end is waiting to receive an open-connection request, when the
- connection end is waiting to receive an acknowledgment of an open-connection
- request, and when the connection is open. The CCB is described in “The ADSP
- Connection Control Block” earlier in this chapter. Alternatively, you can check
- the result code for the dspOpen command when the function completes execution.
- If the function returns the noErr result code, then the connection is open.
-
- 7. Use the dspRead command to read data that your connection end has received
- from the remote connection end. Use the dspWrite command to send data to the
- remote connection end. Use the dspAttention command to send attention messages
- to the remote connection end.
-
- The dspWrite command places data in the send queue. ADSP is a full-duplex,
- symmetric communication protocol. You can send data at any time, and your
- connection end can receive data at any time, even at the same time as you are
- sending data. ADSP transmits the data in the send queue when one of the
- following conditions occurs:
-
- • You call the dspWrite command with the flush parameter set to a nonzero
- number.
-
- • The number of bytes in the send queue equals or exceeds the blocking
- factor that you set with the dspOptions command.
-
- • The send timer expires. The send timer sets the maximum amount of time
- that can pass before ADSP sends all unsent data in the send queue to the
- remote connection end. ADSP calculates the best value to use for this
- timer and sets it automatically.
-
- • A connection event requires that the local connection end send an
- acknowlegment packet to the remote connection end.
-
- If you send more data to the send queue than it can hold, the dspWrite command
- does not complete execution until it has written all the data to the send queue.
- If you execute the dspWrite command asynchronously, ADSP returns control to your
- program and writes the data to the send queue as quickly as it can. This
- technique provides the most efficient use of the send queue by your program and
- by ADSP. Because ADSP does not remove data from the send queue until that data
- has not only been sent but also acknowledged by the remote connection end, using
- the flush parameter to the dspWrite command does not guarantee that the send
- queue is empty. You can use the dspStatus command to determine how much free
- buffer space is available in the send queue.
-
- The dspRead command reads data from the receive queue into your application’s
- private data buffer. ADSP does not transmit data until there is space available
- in the other end’s receive queue to accept it. Because a full receive queue
- slows the communication rate, you should read data from the receive queue as
- often as necessary to keep sufficient buffer space available for new data. You
- can use either of two techniques to do this:
-
- • Allocate a small receive queue (about 600 bytes) and call the dspRead
- command asynchronously. Your completion routine for the dspRead command
- should then call the dspRead command again.
-
- • Allocate a large receive queue and call the dspRead command less
- frequently.
-
- If there is less data in the receive queue than the amount you specify with the
- reqCount parameter to the dspRead command, the command does not complete
- execution until there is enough data available to satisfy the request. There are
- three exceptions to this rule: If the end-of-message bit in the ADSP packet
- header is set, the dspRead command reads the data in the receive queue, returns
- the actual amount of data read in the actCount parameter, and returns the eom
- parameter set to 1. If you have closed the connection end before calling the
- dspRead command (that is, the connection is half open), the command reads
- whatever data is available and returns the actual amount of data read in the
- actCount parameter. If ADSP has closed the connection before you call the
- dspRead command , the function returns the noErr result code with the actCount
- parameter set to 0 and the eom parameter set to 0.
-
- In addition to the byte stream data format implemented by the dspRead and
- dspWrite commands, ADSP provides a mechanism for sending and receiving control
- signals or information separate from the byte stream. You use the dspAttention
- command to send an attention code and an attention message to the remote
- connection end. When your connection end receives an attention message, ADSP’s
- interrupt handler sets the eAttention flag in the userFlags field of the
- connection control block and calls your user routine. Your user routine must
- clear the userFlags field, and can then read the attention code and attention
- message and take whatever action you deem appropriate.
-
- Because ADSP is often used by terminal emulation programs and other applications
- that pass the data they receive on to the user without processing it, attention
- messages provide a mechanism for the applications that are clients of the
- connection ends to communicate with each other. For example, you could use
- attention messages to implement a handshaking and data checking protocol for a
- program that transfers disk files between two applications, neither one of which
- is a file server. Or a database server on a mainframe computer that uses ADSP to
- communicate with Macintosh computer workstations could use the attention
- mechanism to inform the workstations when the database is about to be closed
- down for maintenance.
-
- 8. When you are ready to close the ADSP connection, you can use the dspClose or
- dspRemove commands to close the connection end. Use the dspClose command if you
- intend to open another connection using that connection end, and do not want to
- release the memory you allocated for the connection end. Use the dspRemove
- command if you are completely finished with the connection end and want to
- release the memory.
-
- You can continue to read data from the receive queue after you have called the
- dspClose command, but not after you have called the dspRemove command. You can
- use the dspStatus command to determine whether there is any data remaining in
- the receive queue, or you can read data from the receive queue until both the
- actCount and eom fields of the dspRead parameter block return 0.
-
- If you set the abort parameter for the dspClose or dspRemove commands to 0, then
- ADSP does not close the connection or the connection end until it has sent—and
- received acknowledgment for—all data in the send queue and any pending attention
- messages. If you set the abort parameter to 1, then ADSP discards any data in
- the send queue and any attention messages that have not already been sent.
-
- After you have executed the dspRemove command, you can release the memory you
- allocated for the connection control block and data buffers.
-
- Listing 29-2 illustrates the use of ADSP. It opens the .MPP and .DSP drivers,
- and allocates memory for its internal data buffers, for the CCB, and for the
- send, receive, and attention message buffers. Then it uses the dspInit command
- to establish a connection end, and uses NBP to register the name of the
- connection end on the internet. The routine uses the dspOptions command to set
- the blocking factor to 24 bytes. Next, it uses NBP to determine the address of a
- socket whose name was chosen by the user and sends an open-connection request
- (dspOpen) to that socket. When the dspOpen command completes execution, the
- routine sends data and an attention message to the remote connection end, and
- reads data from its receive buffer. Finally, the routine closes the connection
- end with the dspRemove command and releases the memory it allocated.
-
- Listing 29-2. Using ADSP to establish and use a connection (TO BE PROVIDED)
-
- _______________________________________________________________________________
-
- æKY Creating…and…Using…a…Connection…Listener
- æC »Creating and Using a Connection Listener AppleTalk Manager
- _______________________________________________________________________________
-
- A connection listener is a special sort of ADSP connection end that cannot
- receive or transmit data streams or attention messages. The sole function of a
- connection listener is to wait passively to receive an open-connection request
- and to inform its client, the connection server, when it receives one. The
- connection server can then accept or deny the open-connection request. If it
- accepts the request, the connection server selects a socket to use as a
- connection end, establishes a connection end on that socket, and sends an
- acknowledgement and connection request back to the requesting connection end.
- The connection server can use the same socket as it used for the connection
- listener, or can select a different socket as the connection end.
-
- Use the following procedure to establish a connection listener and to use that
- connection listener to open a connection with a remote connection end:
-
- 1. Use the MPPOpen command to open the .MPP driver and then use the OpenDriver
- command to open the .DSP driver. The OpenDriver routine returns the reference
- number for the .DSP driver; you must supply this reference number each time you
- call the .DSP driver.
-
- 2. Allocate nonrelocatable memory for a connection control block. A connection
- listener does not need send and receive buffers or an attention message buffer.
- The memory that you allocate becomes the property of ADSP when you call the
- dspCLInit command to establish a connection listener. You cannot write any data
- to this memory except through calls to ADSP, and you must ensure that the memory
- remains locked until you call the dspRemove command to eliminate the connection
- end. The connection control block is 242 bytes in size.
-
- 3. Call the dspCLInit command to establish a connection listener. You must
- provide a pointer to the connection control block.
-
- If there is a specific socket that you want to use for the connection listener,
- you can specify the socket number in the localSocket parameter. If you want ADSP
- to assign the socket for you, specify 0 for the localSocket parameter, and ADSP
- returns the socket number when the dspCLInit command completes execution.
-
- 4. If you wish, you can use the NBPRegister function to add the name and
- address of your connection listener to the node’s names table. The NBPRegister
- function is described in the AppleTalk Manager chapter of Volume II.
-
- 5. Use the dspCLListen command to cause the connection listener to wait for an
- open-connection request. Because the dspCLListen command does not complete
- execution until it receives a connection request, you should call this function
- asynchronously. You can specify a value for the filterAddress parameter to
- restrict the network number, node ID, or socket number from which you will
- accept an open-connection request.
-
- When the dspCLListen command receives an open-connection request that meets the
- restrictions of the filterAddress parameter, it returns a noErr result code (if
- you executed the function asynchronously, it places a noErr result code in the
- ioResult parameter) and places values in the parameter block for the remoteCID,
- remoteAddress, sendSeq, sendWindow, and attnSendSeq parameters.
-
- 6. If you want to open the connection, use the dspInit command to establish a
- connection end. You can use any available socket on the node for the connection
- end, including the socket that you used for the connection listener. Because a
- single socket can have more than one CCB connected with it, the socket can
- function simultaneously as a connection end and a connection listener.
-
- You can check the address of the remote socket to determine if it meets your
- criteria for a connection end. Although the filterAddress parameter to the
- dspCLListen command provides some screening of socket addresses, it cannot check
- for network number ranges, for example, or for a specific set of socket numbers.
- If for some reason you want to deny the connection request, call the DSPDeny
- function, specifying the connection control block of the connection listener in
- the ccbRefNum parameter. Because the dspCLListen command completes execution
- when it receives an open-connection request, you must return to step 5 to wait
- for another connection request.
-
- 7. Call the dspOpen command, specifying ocAccept for the ocMode parameter and
- specifying in the ccbRefNum parameter the reference number of the connection end
- that you want to use. When you call the dspOpen command , you must provide the
- values returned by the dspCLListen command for the remoteCID, remoteAddress,
- sendSeq, sendWindow, and attnSendSeq parameters.
-
- You can poll the state field in the connection control block to determine when
- the connection is open. The CCB is described in “The ADSP Connection Control
- Block” earlier in this chapter. Alternatively, you can check the result code for
- the dspOpen command when the function completes execution. If the function
- returns the noErr result code, then the connection is open.
-
- 8. You can now send and receive data and attention messages over the
- connection, as described in the preceding section, “Opening and Maintaining an
- ADSP Connection.” When you are ready to close the connection, you can use the
- dspClose or dspRemove commands, which are also described in the preceding
- section.
-
- 9. When you are finished using the connection listener, you can use the
- dspCLRemove command to eliminate it. Once you have called the dspCLRemove
- command, you can release the memory you allocated for the connection listener’s
- connection control block.
-
- Listing 29-3 illustrates the use of ADSP to establish and use a connection
- listener. It opens the .MPP and .DSP drivers, and allocates memory for the CCB.
- Then it uses the dspCLInit command to establish a connection listener, uses NBP
- to register the name of the connection end on the internet, and uses the
- dspCLListen command to wait for a connection request. When the routine receives
- a connection request, it calls the dspOpen command to complete the connection.
-
- Listing 29-3. Using ADSP to Establish and Use a Connection Listener (TO BE
- PROVIDED)
-
- _______________________________________________________________________________
-
- æKY Writing…a…User…Routine…For…Connection…Events
- æC »Writing a User Routine For Connection Events AppleTalk Manager
- _______________________________________________________________________________
-
- When you execute the dspInit command, you can specify a pointer to a routine
- that you provide (referred to as the user routine). Whenever an unsolicited
- connection event occurs, ADSP sets a flag in the connection control block (CCB)
- and calls the user routine. The user routine must clear the flag to acknowledge
- that it has read the flag field, and can then respond to the event in any manner
- you deem appropriate. The CCB flags are described in “The ADSP Connection
- Control Block” earlier in this chapter. There are four types of unsolicited
- connection events that set flags in the CCB, as follows:
-
- • ADSP has been informed by the remote connection end that the remote
- connection end is about to close the connection. An appropriate reponse
- might be to store a flag indicating that the connection end is about to
- close. When your application regains control, it can then display a
- dialog box informing the user of this event and asking whether the
- application should attempt to reconnect later.
-
- • ADSP has determined that the remote connection end is not responding, and
- so has closed the connection. Your user routine can attempt to open a new
- connection immediately. Alternatively, you can store a flag indicating
- that the connection has closed and, when your application regains
- control, it can display a dialog box asking the user whether to attempt
- to reconnect.
-
- • ADSP has received an attention message from the remote connection end.
- Depending on what you are using the attention message mechanism for, you
- might want to read the attention code in the attnCode field of the CCB
- and the attention message pointed to by the attnPtr field of the CCB.
-
- • ADSP has received a forward reset command from the remote client end, has
- discarded all ADSP data not yet delivered—including the data in the
- local client end’s receive queue—and has resynchronized the connection.
- Your response to this event depends on the purpose for which you are
- using the forward reset mechanism. You might want to resend the last data
- you have sent or inform the user of the event.
-
- When ADSP calls your user routine, the CPU is in interrupt-processing mode and
- register A1 contains a pointer to the CCB of the connection end that generated
- the event. You can examine the userFlags field of the CCB to determine what
- event caused the interrupt, and you can examine the state field of the CCB to
- determine the current state of the connection.
-
- Because the CPU is set to interrupt-processing mode, your user routine must
- preserve all registers other than A0, A1, D0, D1, and D2. Your routine must not
- make any direct or indirect calls to the Memory Manager, and can’t depend on
- handles to unlocked blocks being valid. If you want to use any of your
- application’s global variables, you must save the contents of the A5 register
- before using the variables, and you must restore the A5 register before your
- routine terminates. Listing 29-4 illustrates the use of the CCB to store the
- contents of the A5 register while your routine is executing.
-
- If you want to execute a routine each time an unsolicited connection event
- occurs but the interrupt environment is too restrictive, you can specify a NIL
- pointer to the user routine and periodically poll the userFlags field of the CCB
- instead.
-
- To ensure that you do not lose any attention messages, you must read any
- attention messages into an internal buffer before you clear the bit in the
- userFlags field.
-
- Listing 29-4 is an example of a user routine. When this routine is called, it
- first checks the connection control block to determine the source of the
- interrupt and then clears the bit in the userFlags field of the CCB. If the
- routine has received an attention message, the user routine reads the message
- into an internal buffer before it clears the flag bit.
-
- Listing 29-4. An ADSP user routine (TO BE PROVIDED)
- _______________________________________________________________________________
-
- æKY DSP…Driver…Commands
- æC »DSP Driver Commands AppleTalk Manager
- _______________________________________________________________________________
-
- The .DSP driver implements the AppleTalk Data Stream protocol (ADSP). You send
- commands to ADSP and obtain information about ADSP by executing the .DSP driver
- commands described in this section.
- To use a .DSP driver command, call PBControl passing a pointer to the .DSP
- parameter block as a parameter and the async parameter is a Boolean that
- specifies whether the function is to execute synchronously or asynchronously.
- Set the async parameter to TRUE to execute the function asynchronously.
-
- The .DSP parameter block is shown in “The .DSP Parameter Block” earlier in this
- chapter. The parameters used with each function are described in this section.
-
- For a general discussion of the use of ADSP, see “Using ADSP” earlier in this
- chapter.
-
- _______________________________________________________________________________
-
- æKY Establishing…and…Terminating…an…ADSP…Connection
- æC »Establishing and Terminating an ADSP Connection AppleTalk Manager
- _______________________________________________________________________________
-
- You can use the functions described in this section to
-
- • establish a connection end
- • open a connection
- • assign an identification number to a connection end
- • set the values for parameters that control the behavior of a connection
- end
- • close a connection end
- • eliminate a connection end
-
- The parameter block for the dspInit command looks like this:
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always dspInit
- ¨ 32 ccbRefNum word reference number for CCB
- Æ 34 ccbPtr long pointer to connection control block
- Æ 38 userRoutine long pointer to routine to call on
- connection events
- Æ 42 sendQSize word size in bytes of the send queue
- Æ 44 sendQueue long pointer to send queue
- Æ 48 recvQSize word size in bytes of the receive queue
- Æ 50 recvQueue long pointer to receive queue
- Æ 54 attnPtr long pointer to buffer for incoming
- attention messages
- ´ 58 localSocket byte DDP socket number for this
- connection end
-
- The dspInit command establishes a connection end; that is, it assigns a specific
- socket for use by ADSP and initializes the variables that ADSP uses to maintain
- the connection. The dspInit command does not open the connection end or
- establish a connection with a remote connection end; follow the dspInit command
- with the dspOpen command to perform those tasks. Use the dspCLInit command to
- establish a connection listener. Use the dspRemove command to eliminate a
- connection end.
-
- When you send bytes to a remote connection end, ADSP stores the bytes in a
- buffer called the send queue. It keeps the bytes you sent in the send queue
- until the remote connection end acknowledges their receipt, so that they are
- available to be retransmitted if necessary. When the local connection end
- receives bytes, it stores them in a buffer called the receive queue until you
- read them.
-
- You must allocate memory for the send and receive queues, and for a buffer that
- holds incoming attention messages. You must also allocate a nonrelocatable block
- of memory for the connection control block for this connection end.
-
- Note: When you use the dspInit command, the memory that you allocate becomes
- the property of ADSP. You cannot write any data to this memory except by calling
- ADSP routines, and you must ensure that the memory remains locked until you call
- the dspRemove command to eliminate the connection end.
-
- Parameters
-
- ioResult
- The result of the function. When you execute the function asynchronously, the
- function sets this parameter to 1 and returns a function result of noErr as soon
- as the function begins execution. When the function completes execution, it sets
- the ioResult parameter to the actual result code.
-
- csCode
- The routine selector, you should set this to dspInit for this command.
-
- ccbRefNum
- The reference number for the connection control block. The dspInit command
- returns this number. You must provide this number in all subsequent calls to
- this connection end.
-
- ccbPtr
- A pointer to the connection control block that you allocated. The connection
- control block is 242 bytes in size, and is described in “The ADSP Connection
- Control Block” earlier in this chapter.
-
- userRoutine
- A pointer to a routine that is to be called each time the connection end
- receives an unsolicited connection event. Specify NIL for this parameter if you
- do not want to supply a user routine. Connection events and user routines are
- discussed in “Writing a User Routine For Connection Events” earlier in this
- chapter.
-
- sendQSize
- The size in bytes of the send queue. A queue size of 600 bytes should work well
- for most applications. If you are using ADSP to send a continuous flow of data,
- a larger data buffer will improve performance. If your application is sending
- the user’s keystrokes, a smaller buffer should be adequate. The constant
- minDSPQueueSize indicates the minimum queue size that you can use.
-
-
- sendQueue
- A pointer to the send queue that you allocated.
-
- recvQSize
- The size in bytes of the receive queue. A queue size of 600 bytes should work
- well for most applications. If you are using ADSP to receive a continuous flow
- of data, a larger data buffer will improve performance. If your application is
- receiving a user’s keystrokes, a smaller buffer should be adequate. The constant
- minDSPQueueSize indicates the minimum queue size that you can use.
-
- recvQueue
- A pointer to the receive queue that you allocated.
-
- attnPtr
- A pointer to the attention-message buffer that you allocated. The
- attention-message buffer must be the size of the constant attnBufSize.
-
- localSocket
- The DDP socket number of the socket that you want ADSP to use for this
- connection end. Specify 0 for this parameter to cause ADSP to assign the socket.
- In the latter case, ADSP returns the socket number when the dspInit command
- completes execution.
-
- Result codes
- noErr 0 no error
- ddpSktErr –91 error opening socket
- errDSPQueueSize –1274 send or receive queue too small
-
- The parameter block for the dspOptions command looks like this:
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always dspOptions
- Æ 32 ccbRefNum word reference number of connection end
- Æ 34 sendBlocking word send-blocking threshold
- Æ 38 badSeqMax byte threshold to send retransmit advice
- Æ 39 useCheckSum byte use DDP checksum?
-
- The dspOptions command allows you to set values for several parameters that
- affect the behavior of the local connection end. You can set the options for any
- established connection end, whether open or not.
-
- Parameters
-
- ioResult
- The result of the function. When you execute the function asynchronously, the
- function sets this parameter to 1 and returns a function result of noErr as soon
- as the function begins execution. When the function completes execution, it sets
- the ioResult parameter to the actual result code.
-
- csCode
- The routine selector, you should set this to dspOptions for this command.
-
- ccbRefNum
- The connection control block reference number that was returned by the dspInit
- command.
-
- sendBlocking
- The maximum number of bytes that may accumulate in the send buffer before ADSP
- sends a packet to the remote connection end. ADSP sends a packet before the
- maximum number of bytes accumulates if the period specified by the send timer
- expires, if you execute the dspWrite command with the flush parameter set to 1,
- or if a connection event requires that the local connection end send an
- acknowledgement packet to the remote connection end.
-
- You can set the sendBlocking parameter to any value from 1 byte to the maximum
- size of a packet (572 bytes). If you set the sendBlocking parameter to 0, the
- current value for this parameter is not changed. The default value for the
- sendBlocking parameter is 16 bytes.
-
- badSeqMax
- The maximum number of out-of-sequence data packets that the local connection end
- can receive before requesting the remote connection end to retransmit the
- missing data. Because a connection end does not acknowledge the receipt of a
- data packet received out of sequence, the remote connection end’s retransmit
- timer will expire eventually and it will retransmit the data. The badSeqMax
- allows you to cause the data to be retransmitted before the remote connection
- end’s retransmit timer has expired.
-
- You can set the badSeqMax parameter to any value from 1 to 255. If you set the
- badSeqMax parameter to 0, the current value for this parameter is not changed.
- The default value for the badSeqMax parameter is 3.
-
- useCheckSum
- A flag specifying whether DDP should compute a checksum and include it in each
- packet that it sends to the remote connection end. Set this parameter to 1 to
- cause DDP to use checksums, or to 0 if you do not want DDP to use checksums. The
- default value for useCheckSum is 0.
-
- ADSP cannot include a checksum in a packet that has a short DDP header; that is,
- a packet being sent over LocalTalk to a remote socket that is on the same cable
- as the local socket. Note that the useCheckSum parameter affects only whether
- ADSP includes a checksum in a packet that it is sending. If ADSP receives a
- packet that includes a checksum, it validates the checksum regardless of the
- setting of the useCheckSum parameter.
-
- Result codes
- noErr 0 no error
- errRefNum –1280 bad connection reference number
-
- The parameter block for the dspOpen command looks like this:
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always dspOpen
- Æ 32 ccbRefNum word reference number of connection end
- ¨ 34 localCID word ID of this connection end
- ´ 36 remoteCID word ID of remote connection end
- ´ 38 remoteAddress long remote internet address
- Æ 42 filterAddress long filter for open connection requests
- ´ 46 sendSeq long initial send sequence number
- ´ 50 sendWindow word initial size of remote receive buffer
- Æ 52 recvSeq long initial receive sequence number
- ´ 56 attnSendSeq long attention send sequence number
- Æ 60 attnRecvSeq long attention receive sequence number
- Æ 64 ocMode byte connection opening mode
- Æ 65 ocInterval byte interval between open requests
- Æ 66 ocMaximum byte retries of open connection request
-
- You use the ocMode field of the parameter block to specify the opening mode that
- the dspOpen command is to use. The dspOpen command puts a connection end into
- one of four possible opening modes, as follows:
-
- • The ocRequest mode, in which ADSP attempts to open a connection with the
- socket at the internet address you specify with the remoteAddress
- parameter. If the socket you specify as a remote address is a connection
- listener, it is possible that your application will receive a connection
- acknowledgement and request from a different address than the one to
- which you sent the open-connection request. You can use the filterAddress
- parameter to restrict the addresses with which you will accept a
- connection.
-
- The dspOpen command completes execution in the ocRequest mode when either ADSP
- establishes a connection, your connection end receives a connection denial from
- the remote connection end, your connection end denies the connection request
- returned by a connection listener, or ADSP cannot complete the connection (ADSP
- has exceeded the maximum number of retries that you specified with the ocMaximum
- parameter).
-
- • The ocPassive mode, in which the connection end waits to receive an
- open-connection request from a remote connection end. You can use the
- filterAddress parameter to restrict the addresses from which you will
- accept a connection request.
-
- The dspOpen command completes execution in the ocPassive mode when ADSP
- establishes a connection or when either connection end receives a connection
- denial.
-
- • The ocAccept mode, used by connection servers to complete an
- open-connection dialog. When a connection server is informed by its
- connection listener that the connection listener has received an
- open-connection request, the connection server uses the dspInit command
- to establish a connection end and then calls the dspOpen command in
- ocAccept mode to complete the connection. You must obtain the following
- parameters from the dspCLListen command and provide them to the dspOpen
- command: remoteAddress, remoteCID, sendSeq, sendWindow, and attnSendSeq.
- Connection listeners and connection servers are described in “Creating
- and Using a Connection Listener,” earlier in this chapter, and in
- “Establishing and Terminating an ADSP Connection Listener,” later in this
- chapter.
-
- The dspOpen command completes execution in the ocAccept mode when ADSP
- establishes a connection or when either connection end receives a connection
- denial.
-
- • The ocEstablish mode, in which ADSP considers the connection end
- established and the connection state open. This mode is for use by
- clients that determine their connection-opening parameters without using
- ADSP or the .DSP driver to do so.
-
- You must first use the dspInit command to establish a connection end and then
- execute the dspNewCID command to obtain an identification number for the local
- connection end. You must then communicate with the remote connection end to send
- it the local connection ID and to determine the values of the following
- parameters: remoteAddress, remoteCID, sendSeq, sendWindow, recvSeq, attnSendSeq,
- and attnRecvSeq. Only then can you execute the dspOpen command in the
- ocEstablish mode.
-
- The dspOpen command completes execution in the ocEstablish mode immediately.
- The use of parameters by the dspOpen command depends on the mode in which the
- function is executed, as follows:
-
- ocRequest ocPassive ocAccept ocEstablish
-
- ¨ ioResult ¨ ioResult ¨ ioResult ¨ ioResult
- Æ csCode Æ csCode Æ csCode Æ csCode
- Æ ccbRefNum Æ ccbRefNum Æ ccbRefNum Æ ccbRefNum
- ¨ localCID ¨ localCID ¨ localCID — localCID
- ¨ remoteCID ¨ remoteCID Æ remoteCID Æ remoteCID
- Æ remoteAddress ¨ remoteAddress Æ remoteAddress Æ remoteAddress
- Æ filterAddress Æ filterAddress — filterAddress — filterAddress
- ¨ sendSeq ¨ sendSeq Æ sendSeq Æ sendSeq
- ¨ sendWindow ¨ sendWindow Æ sendWindow Æ sendWindow
- — recvSeq — recvSeq — recvSeq Æ recvSeq
- ¨ attnSendSeq ¨ attnSendSeq Æ attnSendSeq Æ attnSendSeq
- — attnRecvSeq — attnRecvSeq — attnRecvSeq Æ attnRecvSeq
- Æ ocMode Æ ocMode Æ ocMode Æ ocMode
- Æ ocInterval Æ ocInterval Æ ocInterval — ocInterval
- Æ ocMaximum Æ ocMaximum Æ ocMaximum — ocMaximum
-
- Parameters
-
- ioResult
- The result of the function. When you execute the function asynchronously, the
- function sets this parameter to 1 and returns a function result of noErr as soon
- as the function begins execution. When the function completes execution, it sets
- the ioResult parameter to the actual result code.
- csCode The routine selector, you should set this to dspOpen for this command.
-
- ccbRefNum
- The connection control block reference number that was returned by the dspInit
- command for the connection end that you want to use.
-
- localCID
- The identification number of the local connection end. This number is assigned
- by ADSP when the connection is opened. ADSP includes this number in every packet
- sent to a remote connection end. Before you call the dspOpen command in
- ocEstablish mode, you must call the dspNewCID command to cause ADSP to assign
- this value.
-
- remoteCID
- The identification number of the remote connection end. This parameter is
- returned by the dspOpen command in the ocRequest and ocPassive modes. A
- connection server must provide this number to the dspOpen command when the
- server executes the function in ocAccept mode; in this case, the connection
- server obtains the remoteCID value from the dspCLListen command. You must
- provide the remoteCID value to the dspOpen command when you use the function in
- ocEstablish mode.
-
- remoteAddress
- The internet address of the remote socket with which you wish to establish
- communications, consisting of a 2-byte network number, a 1-byte node ID, and a
- 1-byte socket number. You must provide this parameter when you call the dspOpen
- command in the ocRequest or ocEstablish modes. This parameter is returned by the
- dspOpen command when you call the function in the ocPassive mode. When you call
- the dspOpen command in the ocAccept mode, you must use the value for the
- remoteAddress parameter that was returned by the dspCLListen command.
- filterAddress The internet address of the socket from which you will accept a
- connection request. The address consists of three fields, a 2-byte network
- number, a 1-byte node ID, and a 1-byte socket number. Specify 0 for any of these
- fields for which you wish to impose no restrictions. If you specify a filter
- address of $00082500, for example, the connection end will accept a connection
- request from any socket at node $25 of network $0008. Set the filterAddress
- parameter equal to the remoteAddress parameter to accept a connection only with
- the socket to which you sent a connection request.
-
- When you execute the dspOpen command in the ocPassive mode, you can receive a
- connection request from any ADSP connection end on the internet. When you
- execute the dspOpen command in the ocRequest mode, your connection end can
- receive a connection request acknowledgment from an address different from the
- one you specified in the remoteAddress parameter only if the remote address you
- specified was that of a connection listener. in either case, you can use the
- filterAddress parameter to avoid acknowledging unwanted connection requests.
-
- When you execute the dspOpen command in the ocAccept mode, your connection
- listener has already received and decided to accept the connection request. You
- can specify a filter address for a connection listener with the dspCLListen
- command. A connection server can use the dspCLDeny command to deny a connection
- request that was accepted by its connection listener.
-
- You cannot use the filter address when you execute the dspOpen command in
- ocEstablish mode.
-
- sendSeq
- The sequence number of the first byte that the local connection end will send to
- the remote connection end. ADSP uses this number to coordinate communications
- and for error checking. ADSP returns a value for the sendSeq parameter when you
- execute the dspOpen command in the ocRequest or ocPassive modes. When you
- execute the dspOpen command in the ocAccept mode, you must specify the value for
- the sendSeq parameter that was returned by the dspCLListen command. You must
- provide the value for this parameter when you execute the dspOpen command in the
- ocEstablish mode.
-
- sendWindow
- The sequence number of the last byte that the remote connection end has buffer
- space to receive. ADSP uses this number to coordinate communications and for
- error checking. ADSP returns a value for the sendWindow parameter when you
- execute the dspOpen command in the ocRequest or ocPassive modes. When you
- execute the dspOpen command in the ocAccept mode, you must specify the value for
- the sendWindow parameter that was returned by the dspCLListen command. You must
- provide the value for this parameter when you execute the dspOpen command in the
- ocEstablish mode.
-
- recvSeq
- The sequence number of the next byte that the local connection end expects to
- receive. ADSP uses this number to coordinate communications and for error
- checking. You must provide the value for this parameter when you execute the
- dspOpen command in the ocEstablish mode. The dspOpen command does not use this
- parameter when you execute it in any other mode.
-
- attnSendSeq
- The sequence number of the next attention packet that the local connection end
- will transmit. ADSP uses this number to coordinate communications and for error
- checking. ADSP returns a value for the attnSendSeq parameter when you execute
- the dspOpen command in the ocRequest or ocPassive modes. When you execute the
- dspOpen command in the ocAccept mode, you must specify the value for the
- attnSendSeq parameter that was returned by the dspCLListen command. You must
- provide the value for this parameter when you execute the dspOpen command in the
- ocEstablish mode.
-
- attnRecvSeq
- The sequence number of the next attention packet that the local connection end
- expects to receive. ADSP uses this number to coordinate communications and for
- error checking. You must provide the value for this parameter when you execute
- the dspOpen command in the ocEstablish mode. The dspOpen command does not use
- this parameter when you execute it in any other mode.
-
- ocMode
- The mode in which the dspOpen command is to operate, as follows:
-
- Mode Value Meaning
- ocRequest 1 ADSP attempts to open a connection with the socket you
- specify
- ocPassive 2 The connection end waits to receive a connection request
- ocAccept 3 The connection server accepts and acknowledges receipt of a
- connection request
- ocEstablish 4 ADSP considers the connection established and open; you are
- responsible for setting up and synchronizing both connection ends
-
- ocInterval
- The period between transmissions of open-connection requests. If the remote
- connection end does not acknowledge or deny an open-connection request, ADSP
- retransmits the request after a time period specified by this parameter. The
- time period used by ADSP is (ocInterval ¥ 10) ticks; or (ocInterval /
- 6) seconds. For example, if you set the ocInterval parameter to 3, the time
- period between retransmissions is 30 ticks (1/2 second). You can set the
- ocInterval parameter to any value from 1 (1/6 second) to 180 (30 seconds). If
- you specify 0 for the ocInterval parameter, ADSP uses the default value of 6 (1
-
-
- You must provide a value for the ocInterval parameter when you execute the
- dspOpen command in the ocRequest, ocPassive, or ocAccept modes. The dspOpen
- command does not use this parameter when you execute it in the ocEstablish mode.
-
- ocMaximum
- The maximum number of times to retransmit an open-connection request before ADSP
- terminates execution of the dspOpen command. If you specify 0 for the ocMaximum
- parameter, ADSP uses the default value of 3. If you specify 255 for the
- ocMaximum parameter, ADSP retransmits the open-connection request indefinitely
- until the remote connection end either acknowledges or denies the request.
-
- You must provide a value for the ocMaximum parameter when you execute the
- dspOpen command in the ocRequest, ocPassive, or ocAccept modes. The dspOpen
- command does not use this parameter when you execute it in the ocEstablish mode.
-
- Result codes
- noErr 0 no error
- errOpening –1277 attempt to open connection failed
- errState –1278 connection end must be closed
- errAborted –1279 request aborted by dspRemove or dspClose command
- errRefNum –1280 bad connection reference number
-
- The parameter block for the dspNewCID command looks like this:
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always dspNewCID
- Æ 32 ccbRefNum word reference number of connection end
- ¨ 34 newCID word ID of new connection
-
- The dspNewCID command causes ADSP to assign an identification number to a
- connection end without opening the connection end or attempting to establish a
- connection with a remote connection end. Use this function only if you implement
- your own protocol to establish communications with a remote connection end. You
- must first use the dspInit command to establish a connection end. Next, you must
- call the dspNewCID command to obtain a connection-end ID. Then you must
- establish communication with a remote connection end and pass the ID to the
- remote connection end. Finally, you must call the dspOpen command in ocEstablish
- mode to cause ADSP to open the connection. See the description of the dspOpen
- command for more information on establishing a connection in this fashion.
-
- The ioResult parameter returns the result of the function; in the case that you
- call the function asynchronously, the function sets this field to 1 as soon as
- it begins execution, and changes the field to the actual result code when it
- completes execution. The csCode parameter is the routine selector; you should
- set this to dspNewCID for this command. The ccBRefNum parameter is the
- connection control block reference number that was returned by the dspInit
- command. The newCID parameter is the connection-end identification number
- returned by this function. You must provide this number to the client of the
- remote connection end so that it can use it for the remoteCID parameter when it
- calls the dspOpen command.
-
- Result codes
- noErr 0 no error
- errState –1278 connection is not closed
- errRefNum –1280 bad connection reference number
-
- The parameter block for the dspClose command looks like this:
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always dspClose
- Æ 32 ccbRefNum word reference number of connection end
- Æ 34 abort byte abort send requests if not 0
-
- The dspClose command closes the connection end. The connection end is still
- established; that is, ADSP retains ownership of the connection control block,
- send queue, receive queue, and attention-message buffer. You can continue to
- read bytes from the receive queue after you have called the dspClose command.
- Use the dspRemove command instead of the dspClose command if you are through
- reading bytes from the receive queue and want to release the memory associated
- with the connection end. The dspClose command does not return an error if you
- call it for a connection end that is already closed.
-
- The ioResult parameter returns the result of the function; in the case that you
- call the function asynchronously, the function sets this field to 1 as soon as
- it begins execution, and changes the field to the actual result code when it
- completes execution. The csCode parameter is the routine selector; you should
- set this to dspClose for this command. The ccBRefNum parameter is the connection
- control block reference number that was returned by the dspInit command. If the
- abort parameter is nonzero, ADSP cancels any outstanding requests to send data
- packets (such as the dspAttention command) and discards all data in the send
- queue. If the abort parameter is 0, ADSP does not close the connection end until
- all of the data in the send queue and all outstanding attention messages have
- been sent and acknowledged.
-
- Result codes
- noErr 0 no error
- errRefNum –1280 bad connection reference number
-
- The parameter block for the dspRemove command looks like this:
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always dspRemove
- Æ 32 ccbRefNum word reference number of connection end
- Æ 34 abort byte abort connection if not 0
-
- The dspRemove command closes any open connection and eliminates the connection
- end; that is, ADSP no longer retains control of the connection control block,
- send queue, receive queue, and attention-message buffer. You cannot continue to
- read bytes from the receive queue after you have called the dspRemove command.
- After you call the dspRemove command, you can release all of the memory you
- allocated for the connection end if you do not intend to reopen the connection
- end.
-
- The ioResult parameter returns the result of the function; in the case that you
- call the function asynchronously, the function sets this field to 1 as soon as
- it begins execution, and changes the field to the actual result code when it
- completes execution. The csCode parameter is the routine selector; you should
- set this to dspRemove for this command. The ccbRefNum parameter is the
- connection control block reference number that was returned by the dspInit
- command. If the abort parameter is nonzero, ADSP cancels any outstanding
- requests to send data packets (such as the dspAttention command) and discards
- all data in the send queue. If the abort parameter is 0, ADSP does not close the
- connection end until all of the data in the send queue has been sent and
- acknowledged.
-
- Result codes
- noErr 0 no error
- errRefNum –1280 bad connection reference number
- _______________________________________________________________________________
-
- æKY Establishing…and…Terminating…an…ADSP…Connection…Listener
- æC »Establishing and Terminating an ADSP Connection Listener AppleTalk Manager
- _______________________________________________________________________________
-
- A connection listener is a special kind of connection end that listens for
- open-connection requests from remote connection ends. Connection listeners are
- used by connection servers; that is, programs that assign a socket for the local
- connection end only after they receive a connection request from a remote
- connection end. A single connection listener, then, can receive connection
- requests from any number of remote connection ends.
-
- You can use the functions in this section to
-
- • establish a connection listener
- • cause the connection listener to wait for a connection request
- • deny a connection request
- • close and eliminate a connection listener
-
- The parameter block for the dspCLInit command looks like this:
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always dspCLInit
- ¨ 32 ccbRefNum word reference number of connection end
- Æ 34 ccbPtr long pointer to CCB
- ´ 58 localSocket byte local DDP socket number
-
- The dspCLInit command establishes a connection listener; that is, it assigns a
- specific socket for use by ADSP and initializes the variables that ADSP uses to
- maintain a connection listener. The dspCLInit command does not cause the
- connection listener to listen for connection requests; follow the dspCLInit
- command with the dspCLListen command to activate the connection listener. Use
- the dspInit command to establish a connection end that is not a connection
- listener. Use the dspCLRemove command to eliminate a connection listener.
-
- The ioResult parameter returns the result of the function; in the case that you
- call the function asynchronously, the function sets this field to 1 as soon as
- it begins execution, and changes the field to the actual result code when it
- completes execution. The csCode parameter is the routine selector; you should
- set this to dspCLInit for this command.The dspCLInit command returns the
- ccbRefNum parameter, which is the reference number for the connection control
- block. You must provide this number in all subsequent dspCLListen and
- dspCLRemove calls to this connection listener.
- You must allocate memory for a connection control block before you call the
- dspCLInit command. The ccbPtr parameter is a pointer to the connection control
- block that you allocated. The connection control block is 242 bytes, and is
- described in “The ADSP Connection Control Block” earlier in this chapter.
-
- The localSocket parameter is the DDP socket number of the socket that you want
- ADSP to use for this connection end. Specify 0 for this parameter to cause ADSP
- to assign the socket. In the latter case, ADSP returns the socket number when
- the dspCLInit command completes execution.
-
- Result codes
- noErr 0 no error
- ddpSktErr –91 error opening socket
-
- The parameter block for the dspCLListen command looks like this:
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always dspCLListen
- Æ 32 ccbRefNum word reference number of connection end
- ¨ 36 remoteCID word ID of remote connection end
- ¨ 38 remoteAddress long remote internet address
- Æ 42 filterAddress long filter for open connection requests
- ¨ 46 sendSeq long initial send sequence number
- ¨ 50 sendWindow word initial size of remote receive buffer
- ¨ 56 attnSendSeq long attention send sequence number
-
- The dspCLListen command causes a connection listener to listen for connection
- requests. You must have already used the dspCLInit command to establish a
- connection listener before using the dspCLListen command. The dspCLListen
- command is used only by connection servers.
-
- When ADSP receives an open-connection request from a socket that satisfies the
- address requirements of the filterAddress parameter, it returns values for the
- remoteCID, remoteAddress, sendSeq, sendWindow, and attnSendSeq parameters and
- completes execution of the dspCLListen command. You must then either accept the
- open-connection request by calling the dspOpen command in the ocAccept mode or
- deny the request by calling the dspCLDeny command.
-
- You can call the dspCLListen command several times, specifying the same
- connection listener. For example, if you wanted to accept connections from any
- or all of three different addresses, you could call the dspCLListen command
- three times with a different value for the filterAddress parameter each time.
- Note that you must execute the dspCLListen command asynchronously to take
- advantage of this feature.
-
- Parameters
-
- ioResult
- The result of the function. When you execute the function asynchronously, the
- function sets this parameter to 1 and returns a function result of noErr as soon
- as the function begins execution. When the function completes execution, it sets
- the ioResult parameter to the actual result code.
-
- csCode
- The routine selector; you should set this to dspCLListen for this command.
-
- ccbRefNum
- The connection control block reference number that was returned by the dspCLInit
- command.
-
- remoteCID
- The identification number of the remote connection end. You must pass this value
- to the dspOpen command when you open the connection or to the dspCLDeny command
- when you deny the connection request.
-
- remoteAddress
- The internet address of the remote socket that sent a request to open a
- connection. This address consists of a 2-byte network number, a 1-byte node ID,
- and a 1-byte socket number. You must pass this value to the dspOpen command when
- you open the connection or to the dspCLDeny command when you deny the connection
- request.
-
- filterAddress
- The internet address of the socket from which you will accept a connection
- request. The address consists of three fields, a 2-byte network number, a 1-byte
- node ID, and a 1-byte socket number. Specify 0 for any of these fields for which
- you wish to impose no restrictions. If you specify a filter address of
- $00082500, for example, the connection listener will accept a connection request
- from any socket at node $25 of network $0008.
-
- sendSeq
- The sequence number of the first byte that the local connection end will send to
- the remote connection end. ADSP uses this number to coordinate communications
- and for error checking. You must pass this value to the dspOpen command when you
- open the connection.
-
- sendWindow
- The sequence number of the last byte that the remote connection end has buffer
- space to receive. ADSP uses this number to coordinate communications and for
- error checking. You must pass this value to the dspOpen command when you open
- the connection.
-
- attnSendSeq
- The sequence number of the next attention packet that the local connection end
- will transmit. ADSP uses this number to coordinate communications and for error
- checking. You must pass this value to the dspOpen command when you open the
- connection.
-
- Result codes
- noErr 0 no error
- errState –1278 not a connection listener
- errAborted –1279 request aborted by the dspRemove command
- errRefNum –1280 bad connection reference number
-
- The parameter block for the dspCLDeny command looks like this:
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always dspCLDeny
- Æ 32 ccbRefNum word reference number of connection
- listener
- Æ 36 remoteCID word ID of remote connection end
- Æ 38 remoteAddress long remote internet address
-
- The dspCLDeny command is used by a connection server to inform a remote
- connection end that its request to open a connection cannot be honored.
-
- The ioResult parameter returns the result of the function; in the case that you
- call the function asynchronously, the function sets this field to 1 as soon as
- it begins execution, and changes the field to the actual result code when it
- completes execution. The csCode parameter is the routine selector; you should
- set this to dspCLDeny for this command. The ccbRefNum parameter is the reference
- number for the connection listener that received the connection request. This
- number is returned by the dspCLInit command when you establish a connection
- listener. The remoteCID and remoteAddress parameters specify the address and ID
- of the remote connection end. These parameters are returned by the dspCLListen
- command.
-
- Result codes
- noErr 0 no error
- errState –1278 not a connection listener
- errAborted –1279 request aborted by the dspRemove command
- errRefNum –1280 bad connection reference number
-
- The parameter block for the dspCLRemove command looks like this:
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always dspCLRemove
- Æ 32 ccbRefNum word reference number of connection
- listener
- Æ 34 abort byte abort connection listener if not 0
-
- The dspCLRemove command closes a connection end used as a connection listener.
- You can release the memory you allocated for the connection control block if you
- do not intend to reopen the connection end.
-
- The ioResult parameter returns the result of the function; in the case that you
- call the function asynchronously, the function sets this field to 1 as soon as
- it begins execution, and changes the field to the actual result code when it
- completes execution. The csCode parameter is the routine selector; you should
- set this to dspCLRemove for this command. The ccbRefNum parameter is the
- connection control block reference number that was returned by the dspCLInit
- command. If the abort parameter is nonzero, ADSP cancels any outstanding
- requests to send packets (such as the dspCLDeny command).
-
- Result codes
- noErr 0 no error
- errRefNum –1280 bad connection reference number
- _______________________________________________________________________________
-
- æKY Maintaining…an…ADSP…Connection
- æC »Maintaining an ADSP Connection AppleTalk Manager
- _______________________________________________________________________________
-
- Once you have established a connection end and opened a connection, you must be
- able to send and receive data over the connection. You can use the functions in
- this section to
-
- • determine the status of a connection
- • read bytes from the connection end’s receive queue
- • write bytes to the connection end’s send queue and transmit them to the
- remote connection end
- • send an attention message to the remote connection end
- • discard all data that has been sent but not yet delivered, and reset the
- connection
-
- The parameter block for the dspStatus command looks like this:
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always dspStatus
- Æ 32 ccbRefNum word reference number of connection end
- ¨ 34 statusCCB pointer pointer to connection control block
- ¨ 38 sendQPending word bytes waiting to be sent or
- acknowledged
- ¨ 40 sendQFree word available send queue in bytes
- ¨ 42 recvQPending word bytes waiting to be read from queue
- ¨ 44 recvQFree word available receive queue in bytes
-
- The dspStatus command returns the number of bytes waiting to be read and sent
- and the space available in the send and receive queues. This function also
- returns a pointer to the connection control block, which contains information
- about the state of the connection end and about connection events received by
- the connection end. The connection control block is described in “The ADSP
- Connection Control Block” earlier in this chapter.
-
- The ioResult parameter returns the result of the function; in the case that you
- call the function asynchronously, the function sets this field to 1 as soon as
- it begins execution, and changes the field to the actual result code when it
- completes execution. The csCode parameter is the routine selector; you should
- set this to dspStatus for this command. The ccbRefNum parameter is the
- connection control block reference number that was returned by the dspInit
- command. The statusCCB parameter returns a pointer to the connection control
- block.
-
- The sendQPending parameter indicates the number of bytes of data in the send
- queue, including one byte for each end-of-message (EOM) indicator in the send
- queue. (ADSP counts one byte for each EOM, even though there is no actual data
- corresponding to the end-of-message indicator.) The send queue contains all data
- that has been sent to ADSP for transmission that has not yet been acknowledged.
- Some of the data in the send queue might have already been transmitted, but ADSP
- retains it in the send queue until the remote connection end acknowledges its
- receipt in case the data has to be retransmitted. The sendQFree parameter
- indicates the buffer space available for additional data in the send queue, in
- bytes.
-
- The recvQPending parameter indicates the number of bytes in the receive queue,
- including one byte for each EOM if the end-of-message bit is set in an ADSP
- packet header. The receive queue contains all of the data that has been received
- by the connection end but not yet read by the connection end’s client. The
- recvQFree parameter indicates the buffer space available for additional data in
- the receive queue, in bytes.
-
- Result codes
- noErr 0 no error
- errRefNum –1280 bad connection reference number
-
- The parameter block for the dspRead command looks like this:
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always dspRead
- Æ 32 ccbRefNum word reference number of connection end
- Æ 34 reqCount word requested number of bytes
- ¨ 36 actCount word actual number of bytes read
- Æ 38 dataPtr pointer pointer to data buffer
- ¨ 42 eom byte 1 if end-of-message; 0 otherwise
-
- The dspRead command reads bytes from the connection end’s receive queue and
- places them in a buffer that you specify. You can continue to read bytes as long
- as there is data in the receive queue, even after you or the remote end have
- called the dspClose or dspRemove commands. The dspRead command completes
- execution when it has read the number of bytes you specify, or when it
- encounters an end-of-message (that is, the last byte of data in an ADSP packet
- that has the end-of-message bit set in the packet header).
-
- You can call the dspStatus command to determine the number of bytes remaining to
- be read from the read queue, or you can continue to call the dspRead command
- until the actCount and eom parameters both return 0.
-
- The ioResult parameter returns the result of the function; in the case that you
- call the function asynchronously, the function sets this field to 1 as soon as
- it begins execution, and changes the field to the actual result code when it
- completes execution. The csCode parameter is the routine selector; you should
- set this to dspRead for this command. The ccbRefNum parameter is the connection
- control block reference number that was returned by the dspInit command.
- You specify the number of bytes to read with the reqCount parameter, and use the
- dataPtr parameter to provide a pointer to the buffer into which ADSP should
- place the data. ADSP returns the actual number of bytes read in the actCount
- parameter. If the last byte read constitutes an end-of-message, ADSP sets the
- eom parameter to 1.
-
- Result codes
- noErr 0 no error
- errFwdReset –1275 read terminated by forward reset
- errState –1278 state isn’t open, closing, or closed
- errAborted –1279 request aborted by dspRemove or dspClose command
- errRefNum –1280 bad connection reference number
-
- The parameter block for the dspWrite command looks like this:
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always dspWrite
- Æ 32 ccbRefNum word reference number of connection end
- Æ 34 reqCount word requested number of bytes
- ¨ 36 actCount word actual number of bytes written
- Æ 38 dataPtr pointer pointer to data buffer
- Æ 42 eom byte 1 if end of message; 0 otherwise
- Æ 43 flush byte 1 to send data now; 0 otherwise
-
- The dspWrite command writes bytes into the connection end’s send queue. The send
- queue contains all data that has been sent to ADSP for transmission that has not
- yet been acknowledged. Some of the data in the send queue might have already
- been transmitted, but ADSP retains it in the send queue until the remote
- connection end acknowledges its receipt in case the data has to be
- retransmitted. The dspWrite command completes execution when it has copied all
- of the data from the data buffer into the ADSP send queue.
-
- ADSP transmits the data in the send queue when the remote connection end has
- room to accept the data and one of the following conditions occurs:
-
- • You call the dspWrite command with the flush parameter set to a nonzero
- number.
-
- • The number of bytes in the send queue equals or exceeds the blocking
- factor; you use the sendBlocking parameter to the dspOptions command to
- set the blocking factor.
-
- • The send timer expires.
-
- • A connection event requires that the local connection end send an
- acknowlegment packet to the remote connection end.
-
- The ioResult parameter returns the result of the function; in the case that you
- call the function asynchronously, the function sets this field to 1 as soon as
- it begins execution, and changes the field to the actual result code when it
- completes execution. The csCode parameter is the routine selector; you should
- set this to dspWrite for this command. The ccbRefNum parameter is the connection
- control block reference number that was returned by the dspInit command.
-
- You specify the number of bytes to write with the reqCount parameter, and use
- the dataPtr parameter to provide a pointer to the buffer from which ADSP should
- read the data. The dspWrite command returns the actual number of bytes written
- in the actCount parameter. If the last byte written constitutes an
- end-of-message, set the eom parameter to 1. You can also set the reqCount
- parameter to 0 and the eom parameter to 1 to indicate that the last byte you
- sent the previous time you called the dspWrite command was the end of the
- message.
-
- You can set the reqCount parameter to a value larger than the size of the send
- queue. If you do so, the dspWrite command writes as much data as it can into the
- send queue, sends the data and waits for acknowledgement, and then writes more
- data into the send queue until it has written the amount of data you requested.
- In this case, the function does not complete execution until it has finished
- writing all of the data into the send queue.
-
- The high-order bits of the eom parameter are reserved for use by ADSP; you must
- leave these bits equal to 0.
-
- Set the flush parameter to 1 to cause ADSP to immediately transmit any data in
- the send queue that has not already been transmitted. Set the flush parameter to
- 0 to allow data to accumulate in the send queue until another condition occurs
- that causes data to be transmitted. The high-order bits of the flush parameter
- are reserved for use by ADSP; you must leave these bits equal to 0.
-
- Result codes
- noErr 0 no error
- errState –1278 connection is not open
- errAborted –1279 request aborted by dspRemove or dspClose command
- errRefNum –1280 bad connection reference number
-
- The parameter block for the dspAttention command looks like this:
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always dspAttention
- Æ 32 ccbRefNum word reference number of connection end
- Æ 34 attnCode word client attention code
- Æ 36 attnSize word size of attention data in bytes
- Æ 38 attnData pointer pointer to attention data
-
- The dspAttention command sends an attention code and an attention message to the
- remote connection end. Attention codes and attention messages can have any
- meaning that your application and the application at the remote connection end
- both recognize. The purpose of attention codes and messages is to allow clients
- of ADSP to send messages outside the normal data stream. For example, if a
- connection end on a mainframe computer is connected to several connection ends
- in Macintosh computers being used as remote terminals, the mainframe computer
- might wish to inform the remote terminals that all connections will be
- terminated in ten minutes. The mainframe application could send an attention
- message to each of the remote terminals informing them of this fact, and the
- terminal emulation programs in the Macintosh computers could then display an
- alert message on the screen so that the users could prepare to shut down.
-
- The ioResult parameter returns the result of the function; in the case that you
- call the function asynchronously, the function sets this field to 1 as soon as
- it begins execution, and changes the field to the actual result code when it
- completes execution. The csCode parameter is the routine selector; you should
- set this to dspAttention for this command. The ccbRefNum parameter is the
- connection control block reference number that was returned by the dspInit
- command.
-
- The attnCode parameter is the attention code that you wish to send to the remote
- connection end. You can use any value from $0000 through $EFFF for the attention
- code. The values $F000 through $FFFF are reserved for use by ADSP. The attnSize
- parameter is the size in bytes of the attention message you wish to send, and
- the attnData parameter provides a pointer to the attention message. The
- attention message can be any size from 0 through 570 bytes. There are no
- restrictions on the content of the attention message.
-
- Result codes
- noErr 0 no error
- errAttention –1276 attention message too long
- errState –1278 connection is not open
- errAborted –1279 request aborted by dspRemove or dspClose command
- errRefNum –1280 bad connection reference number
-
- The parameter block for the dspReset command looks like this:
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always dspReset
- Æ 32 ccbRefNum word reference number of connection end
-
- The dspReset command causes ADSP to discard all data in the send queue, all data
- in transit to the remote connection end, and all data in the remote connection
- end’s receive queue that the client has not yet read. This process is known as a
- forward reset. ADSP then resynchronizes the connection. You can determine that
- your connection end has received a forward reset and has discarded all data in
- the receive queue by checking the eFwdReset flag in the userFlags field of the
- connection control block. The connection control block is described in “The ADSP
- Connection Control Block” earlier in this chapter.
-
- The ioResult parameter returns the result of the function; if you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and changes the field to the actual result code when it completes
- execution. The csCode parameter is the routine selector; you should set this to
- dspReset for this command. The ccbRefNum parameter is the connection control
- block reference number that was returned by the dspInit command.
-
- Result codes
- noErr 0 no error
- errState –1278 connection is not open
- errAborted –1279 request aborted by dspRemove or dspClose command
- errRefNum –1280 bad connection reference number
- _______________________________________________________________________________
-
- æKY The….ATP…Driver
- æC »THE .ATP DRIVER AppleTalk Manager
- _______________________________________________________________________________
-
- AppleTalk Phase 2 includes two changes to the .ATP driver: you can now cancel
- all calls to the ATPGetRequest function that are pending execution, and you can
- now set the release timer for ATP exactly-once (XO) service to one of five
- different values.
- _______________________________________________________________________________
-
- æKY Canceling…All…Calls…to…the…ATPGetRequest…Function
- æC »Canceling All Calls to the ATPGetRequest Function AppleTalk Manager
- _______________________________________________________________________________
-
- The ATPGetRequest function sets a socket to receive a request sent by another
- socket. If you call the ATPGetRequest function asynchronously, you can have
- several calls to the function simultaneously pending execution. The
- ATPKillAllGetReq function cancels all calls to the ATPGetRequest function
- pending for a specific socket without closing the socket.
-
- FUNCTION ATPKillAllGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- Æ 26 csCode word always ATPKillAllGetReq
- Æ 28 atpSocket byte socket for which to cancel all calls to ATPGetRequest
-
- The ATPKillAllGetReq function cancels all pending asynchronous calls to the
- ATPGetRequest function for the socket you specify with the atpSocket parameter.
- Unlike the ATPCloseSocket function, the ATPKillAllGetReq function does not close
- the socket. You should call the ATPKillAllGetReq function before closing a
- socket. The csCode parameter is a routine selector, automatically set by the MPW
- interface. It is always equal to ATPKillAllGetReq for this function.
-
- Result codes
- noErr 0 no error
- cbNotFound –1102 control block not found; no pending asynchronous calls
- _______________________________________________________________________________
-
- æKY Setting…the…Timeout…Value…For…the…ATP…Release…Timer
- æC »Setting the Timeout Value For the ATP Release Timer AppleTalk Manager
- _______________________________________________________________________________
-
- The .ATP driver maintains a timer, called the release timer, for each call to
- the PSendResponse function that is part of an exactly-once transaction. If the
- timer expires before the transaction is complete (that is, before the socket
- receives the transaction release packet), the driver completes the PSendResponse
- function. Before AppleTalk Phase 2, the release timer was always set to 30
- seconds. To set the other connection end’s release timer to another value, set
- bit 2 of the atpFlags field in the parameter block for the PSendRequest or the
- PNSendRequest function and add a new field to the parameter block at offset 50:
- the TRelTime field. The lower three bits of the TRelTime field indicate the time
- to which the release timer is to be set, as follows:
-
- TRelTime Field Setting of Release Timer
- 000 30 seconds
- 001 1 minute
- 010 2 minutes
- 011 4 minutes
- 100 8 minutes
-
- Note: The nodes at both ends of the ATP connection must be running AppleTalk
- Phase 2 drivers for this feature to work.
-
- Exactly-once service, the release timer, and the PSendRequest function are
- described in the AppleTalk Manager chapter of Volume II. The ATP parameter block
- and the PSendRequest function are described in the AppleTalk Manager chapter of
- Volume V.
-
- _______________________________________________________________________________
-
- æKY The….XPP…Driver
- æC »THE .XPP DRIVER AppleTalk Manager
- _______________________________________________________________________________
-
- The .XPP driver provides these functions that return information about zones:
-
- • The GetMyZone function returns the AppleTalk zone name of the node on
- which your application is running.
-
- • The GetLocalZones function returns a list of zone names on the network
- that includes the node on which your application is running.
-
- • The GetZoneList function returns a complete list of zones on the internet.
-
- Note: Before the AppleTalk Phase 2 version of the .XPP driver, you had to use
- ATP to obtain zone information and request it directly from a router. The ZIP
- functions provided by the new version of the .XPP driver make it much easier for
- you to obtain this information. To ensure compatibility with future versions of
- AppleTalk, you should always use the functions described in this section to
- obtain zone information.
-
- The .XPP driver uses a parameter block defined by the xCallParam record for the
- GetMyZone, GetLocalZones, and GetZoneList functions.
-
- xCallParam = PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: INTEGER; {queue type}
- ioTrap: INTEGER; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OsErr; {result code}
- ioNamePtr: StringPtr;{used only for Open routine}
- ioVRefNum: INTEGER; {volume reference number}
- ioRefNum: INTEGER; {driver reference number}
- csCode: INTEGER; {primary command code}
- xppSubCode: INTEGER; {secondary command code}
- xppTimeOut: Byte; {timeout period for .XPP}
- xppRetry: Byte; {retry count}
- filler: INTEGER; {reserved}
- zipBuffPtr: Ptr; {returned zone names}
- zipNumZones: INTEGER; {number of zones returned}
- zipLastFlag: Byte; {nonzero when all zone names have been returned}
- filler Byte; {reserved}
- zipInfoField: PACKED ARRAY[1..70] of Byte {reserved for use by .XPP}
- END;
-
- XCallParamPtr = ^XCallParam;
-
- As for all other AppleTalk Manager preferred interface functions, the MPW
- interface calls the Device Manager PBControl function to implement these ZIP
- protocol functions. The qLink, qType, ioTrap, ioCmdAddr, ioNamePtr, and
- ioVRefNum fields are filled in by the Device Manager; your application should
- not have to set or read these parameters. The ioResult parameter returns the
- result of the function; in the case that you call the function asynchronously,
- the Device Manager sets this field to 1 as soon as you call the function, and
- changes the field to the actual result code when the function completes
- execution. The ioCompletion parameter is a pointer to a completion routine that
- you can provide; the Device Manager calls your completion routine when it
- completes execution of the PBControl function. If you are not providing a
- completion routine, specify NIL for this field. The ioRefNum, csCode, and
- xppSubCode fields specify the driver and the command to be executed; the MPW
- Pascal interface fills in these fields for you.
-
- _______________________________________________________________________________
-
- æKY Using…the….XPP…Driver…to…Obtain…Zone…Information
- æC »Using the .XPP Driver to Obtain Zone Information AppleTalk Manager
- _______________________________________________________________________________
-
- The Zone Information Protocol obtains the zone information by using the
- AppleTalk Transaction Protocol to send an information request to a router. The
- xppTimeOut field specifies the amount of time, in seconds, that the .ATP driver
- should wait between attempts to obtain the data. The xppRetry field specifies
- the number of times the .ATP driver should attempt to obtain the data before
- returning the reqFailed (request failed) result code.
-
- The zipBuffPtr field is a pointer to a data buffer that you must allocate. This
- buffer must be 578 bytes for the GetZoneList and GetLocalZones functions and 33
- bytes for the GetMyZone function. The Zone Information Protocol returns the zone
- names (as a packed array of packed Pascal strings) into this buffer. The
- zipNumZones field returns the actual number of zone names that ZIP placed in the
- buffer. You must set the zipLastFlag field to 0 before you execute the
- GetZoneList or GetLocalZones functions. If the zipLastFlag parameter is still 0
- when the command has completed execution, then the ZIP is waiting to return more
- zone names. In this case you must empty the buffer (or allocate a new one) and
- call the GetZoneList or GetLocalZones function again immediately. When there are
- no more zone names to send, ZIP sets the zipLastFlag field to a nonzero value.
-
- The zipInfoField field is a 70-byte data buffer that you must allocate for use
- by the .XPP driver. The first time you call any of these functions, you must set
- the first word of this field to 0. You must not change any values in this field
- subsequently.
-
- Listing 29-5 illustrates the use of the GetZoneList function. The GetLocalZones
- function operates in exactly the same fashion.
-
- Listing 29-5. Using the GetZoneList function (TO BE PROVIDED)
-
- Listing 29-6 illustrates the use of the GetMyZone function.
-
- Listing 29-6. Using the GetMyZone function (TO BE PROVIDED)
- _______________________________________________________________________________
-
- æKY XPP…Driver…Routines
- æC »XPP Driver Routines AppleTalk Manager
- _______________________________________________________________________________
-
- The .XPP driver provides three functions that obtain information about zones.
- All three functions use the Zone Information Protocol to return the names of
- zones: The GetMyZone function returns the AppleTalk zone name of the node on
- which your application is running; the GetLocalZones function returns a list of
- zone names on the network that includes the node on which your application is
- running; and the GetZoneList function returns a complete list of zones on the
- internet.
-
- Assembly-language note: The .XPP driver functions all use the same value
- (xCall, which is equal to 246) for the csCode parameter to the xCallParam
- parameter block. The xCall routine uses the value of the xppSubCode parameter to
- distinguish between the functions, as follows:
-
- Function xppSubCode Value
- GetMyZone getMyZone 7
- GetLocalZones getLocalZones 5
- GetZoneList getZoneList 6
-
- FUNCTION GetMyZone (thePBptr:XCallParamPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word routine selector; always xCall
- Æ 28 xppSubCode word routine selector; getMyZone
- Æ 30 xppTimeOut byte retry interval in seconds
- Æ 31 xppRetry byte retry count
- Æ 34 zipBuffPtr long pointer to data buffer
- Æ 42 zipInfoField 70 bytes for use by ZIP; first word set to 0
-
- The GetMyZone function returns only the zone name of the node on which your
- application is running.
-
- The ioResult parameter returns the result of the function; if you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and changes the field to the actual result code when it completes
- execution. The csCode and xppSubCode parameters are routine selectors and are
- automatically set by the MPW interface to xCall and getMyZone for this function.
- The xppTimeOut field specifies the amount of time, in seconds, that the .ATP
- driver should wait between attempts to obtain the data. A value of 3 or 4 for
- the xppTimeOut field generally gives good results. The xppRetry field specifies
- the number of times the .ATP driver should attempt to obtain the data before
- returning the ReqFailed (request failed) result code. A value of 3 or 4 for the
- xppRetry field usually works well.
-
- The zipBuffPtr is a pointer to a 33-byte data buffer that you must allocate. The
- Zone Information Protocol returns the zone name into this buffer as a Pascal
- string. The zipInfo field is a 70-byte data buffer that you must allocate for
- use by ZIP. You must set the first word of this buffer to 0 before you call the
- GetMyZone function.
-
- Result codes
- noErr 0 no error
- noBridgeErr –93 no router is available
- reqFailed –1096 Request to contact router failed; retry count exceeded
-
- FUNCTION GetLocalZones (thePBptr:XCallParamPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word routine selector; always xCall
- Æ 28 xppSubCode word routine selector; getLocalZones
- Æ 30 xppTimeOut byte retry interval in seconds
- Æ 31 xppRetry byte retry count
- Æ 34 zipBuffPtr pointer pointer to data buffer
- ¨ 38 zipNumZones word number of names returned
- ¨ 40 zipLastFlag byte nonzero if no more names
- Æ 42 zipInfoField 70 bytes for use by ZIP; first word set to 0
-
- The GetLocalZones function returns a list of all the zone names on the local
- network; that is, the network that includes the node on which your application
- is running.
-
- The ioResult parameter returns the result of the function; if you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and changes the field to the actual result code when it completes
- execution. The csCode and xppSubCode parameters are routine selectors and are
- automatically set by the MPW interface to xCall and getLocalZones for this
- function. The xppTimeOut field specifies the amount of time, in seconds, that
- the .ATP driver should wait between attempts to obtain the data. A value of 3 or
- 4 for the xppTimeOut field generally gives good results. The xppRetry field
- specifies the number of times the .ATP driver should attempt to obtain the data
- before returning the ReqFailed (request failed) result code. A value of 3 or 4
- for the xppRetry field usually works well.
-
- The zipBuffPtr is a pointer to a 578-byte data buffer that you must allocate.
- The Zone Information Protocol returns the zone names into this buffer as a
- packed array of packed Pascal strings. The zipNumZones parameter returns the
- number of zone names that ZIP placed in the data buffer.
-
- The .XPP driver sets the zipLastFlag field to 1 if there are no more zone names
- for your network. If the zipLastFlag field is still 0 when the GetLocalZones
- function has completed execution, you must empty the data buffer pointed to by
- the zipBuffPtr parameter and immediately call the GetLocalZones function again
- without changing the value in the zipInfoField parameter. The zipInfofield
- parameter is a 70-byte data buffer that you must allocate for use by ZIP. You
- must set the first word of this buffer to 0 before you call the GetLocalZones
- function the first time, and not change the contents of this field thereafter.
-
- FUNCTION GetZoneList (thePBptr:XCallParamPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word routine selector; always xCall
- Æ 28 xppSubCode word routine selector; getZoneList
- Æ 30 xppTimeOut byte retry interval in seconds
- Æ 31 xppRetry byte retry count
- Æ 34 zipBuffPtr pointer pointer to data buffer
- ¨ 38 zipNumZones word number of names returned
- ¨ 40 zipLastFlag byte nonzero if no more names
- Æ 42 zipInfoField 70 bytes for use by ZIP; first word set to 0
-
- The GetZoneList function returns a complete list of all the zone names on the
- internet. Use the GetLocalZones function to obtain a list of only the zone names
- on the local network.
-
- The ioResult parameter returns the result of the function; if you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and changes the field to the actual result code when it completes
- execution. The csCode and xppSubCode parameters are routine selectors and are
- automatically set by the MPW interface to xCall and getZoneList for this
- function. The xppTimeOut field specifies the amount of time, in seconds, that
- the .ATP driver should wait between attempts to obtain the data. A value of 3 or
- 4 for the xppTimeOut field generally gives good results. The xppRetry field
- specifies the number of times the .ATP driver should attempt to obtain the data
- before returning the ReqFailed (request failed) result code. A value of 3 or 4
- for the xppRetry field usually works well.
-
- The zipBuffPtr is a pointer to a 578-byte data buffer that you must allocate.
- The Zone Information Protocol returns the zone names into this buffer as Pascal
- strings. The zipNumZones parameter returns the number of zone names that ZIP
- placed in the data buffer.
-
- The .XPP driver sets the zipLastFlag field to 1 if there are no more zone names
- for the internet. If the zipLastFlag field is still 0 when the GetZoneList
- function has completed execution, you must empty the data buffer pointed to by
- the zipBuffPtr parameter and immediately call the GetZoneList function again
- without changing the value in the zipInfoField parameter. The zipInfofield
- parameter is a 70-byte data buffer that you must allocate for use by ZIP. You
- must set the first word of this buffer to 0 before you call the GetZoneList
- function the first time, and not change the contents of this field thereafter.
-
- _______________________________________________________________________________
-
- æKY The….ENET…Driver
- æC »THE .ENET DRIVER AppleTalk Manager
- _______________________________________________________________________________
-
- The .ENET driver is an Ethernet driver for the EtherTalk NuBus card that is
- manufactured by Apple Computer, Inc. The .ENET driver is normally called by the
- AppleTalk Manager through the EtherTalk 'adev' file when the user has selected
- EtherTalk from the Network control panel. You can write your own protocol stack
- or application that uses the .ENET driver directly, rather than through
- AppleTalk. This section describes how to open the .ENET driver, how to send data
- to it directly for transmission over the Ethernet network, and how to write a
- protocol handler to receive data from the network.
-
- If you write an Ethernet driver for use with your own Ethernet NuBus card, you
- should provide the features and functions described in this chapter and should
- name your driver .ENET. If you write an Ethernet driver for use with a non-NuBus
- network interface (such as an Ethernet card for the Macintosh SE/30 or an
- Ethernet connection through the SCSI port), you should provide the features and
- functions described in this chapter for the .ENET driver and should name your
- driver .ENET0. If you do so, any software written to use the .ENET driver should
- work with your driver.
-
- _______________________________________________________________________________
-
- æKY Changing…the…Ethernet…Hardware…Address
- æC »Changing the Ethernet Hardware Address AppleTalk Manager
- _______________________________________________________________________________
-
- Each Ethernet NuBus card or other Ethernet hardware interface device contains a
- unique 6-byte hardware address assigned by the manufacturer of the device. The
- .ENET driver normally uses this address to determine whether to receive a
- packet. To change the hardware address for your node, place in the System file a
- resource of type 'eadr' with a resource ID equal to the slot number of the
- Ethernet NuBus card. If the Ethernet device is not a NuBus card (it might be a
- slot card in a Macintosh SE/30, for example), use a resource ID of 0.
-
- The 'eadr' resource consists only of a 6-byte number. Do not use the broadcast
- address or a multicast address for this number. (The broadcast address is
- $FF-FF-FF-FF-FF-FF. A multicast address is any Ethernet address in which the
- low-order bit of the high-order byte is set to 1.) When you open the .ENET
- driver, it looks for an 'eadr' resource. If it finds one, the driver substitutes
- the number in this resource for the Ethernet hardware address and uses it until
- the driver is closed or reset.
-
- Note: To avoid address collisions, you should never arbitrarily change the
- Ethernet hardware address. This feature should be used only by a system
- adiministrator who can keep track of all the Ethernet addresses in the system.
-
- _______________________________________________________________________________
-
- æKY Opening…the….ENET…Driver
- æC »Opening the .ENET Driver AppleTalk Manager
- _______________________________________________________________________________
-
- Before you use the OpenSlot function to open the .ENET driver, you must
- determine which NuBus slots contain EtherTalk cards. The OpenSlot function is
- described in the Device Manager chapter of Volume V. Use the GetsRsrc function
- described in the Slot Manager chapter of this volume to determine which NuBus
- slots contain cards and the type of each NuBus card installed. EtherTalk NuBus
- cards return the string CatNetwork in the field spCategory of the GetsRsrc
- function parameter block, and return the string TypEthernet in the field spType.
-
- Listing 29-7 illustrates the use of the GetsRsrc function and the OpenSlot
- function to open the .ENET driver.
-
- Listing 29-7. Finding an EtherTalk card and opening the .ENET Driver (TO BE
- PROVIDED)
- _______________________________________________________________________________
-
- æKY Using…a…Write-Data…Structure…to…Transmit…Ethernet…Data
- æC »Using a Write-Data Structure to Transmit Ethernet Data AppleTalk Manager
- _______________________________________________________________________________
-
- When you use the EWrite function to send data to the .ENET driver for
- transmission over the Ethernet network, you provide a pointer to a write-data
- structure (Figure 29-4). A write-data structure contains a series of pairs of
- length words and pointers. Each pair indicates the length and location of a
- portion of the data that constitutes the packet to be sent over the network. The
- first length-pointer pair points to a 14-byte header block, which starts with
- the destination node hardware address. Note that this is not the AppleTalk
- address, but is the hardware address of the destination node. If you are calling
- the .ENET driver directly, you must obtain the Ethernet address of the
- destination node yourself; AppleTalk cannot provide it.
-
- The next 6 bytes of the header block are reserved for use by the .ENET driver.
- These bytes are followed by the 2-byte Ethernet protocol type. Data may follow
- the header block; all other length-pointer pairs point to data. The write-data
- structure terminates with a NIL word.
-
- ø 29.3 Ethernet Write-Data Structure
-
- When you first open the .ENET driver, it allocates a 768-byte buffer that it
- uses for transmitting data packets. This buffer is large enough to hold the
- largest EtherTalk packet, which is 617 bytes in size. If you want to transmit
- data packets larger than 768 bytes, call the ESetGeneral function. The .ENET
- driver then allocates a large enough data buffer to send packets up to 1514
- bytes in size.
-
- Listing 29-8 defines an Ethernet write-data structure and then calls the EWrite
- function to send a data packet over Ethernet.
-
- Listing 29-8. Sending a Data Packet Over Ethernet (TO BE PROVIDED)
- _______________________________________________________________________________
-
- æKY Using…the…Default…Ethernet…Protocol…Handler…to…Read…Data
- æC »Using the Default Ethernet Protocol Handler to Read Data AppleTalk Manager
- _______________________________________________________________________________
-
- When the EtherTalk Nubus card or other Ethernet hardware receives a data packet,
- it generates an interrupt to the CPU. The interrupt handler in ROM determines
- the source of the interrupt and calls the .ENET driver. The .ENET driver reads
- the packet header to determine the protocol type of the data packet and checks
- to see if any client has specified that protocol type in a call to the EAttachPH
- function. If so, the client either specified a NIL pointer to a protocol
- handler, or the client provided its own protocol handler. If the client
- specified a NIL pointer, the .ENET driver uses its default protocol handler to
- read the data. If no one has specified that protocol type in a call to the
- EAttachPH function, the .ENET driver discards the data. The EAttachPH function
- is described in
- “Attaching and Detaching an Ethernet Protocol Handler” later in this chapter.
-
- The default protocol handler checks for an ERead function pending execution and
- places the entire packet—including the packet header—into the buffer specified
- by that function. The function returns the number of bytes actually read. If the
- packet is larger than the data buffer, the ERead function places as much of the
- packet as will fit into the buffer and returns the buf2SmallErr result code.
-
- Call the ERead function asynchronously to await the next data packet. When the
- .ENET driver receives the data packet, it completes execution of the ERead
- function and calls your completion routine. Your completion routine should call
- the ERead function again so that there is always an ERead function pending
- execution. If the .ENET driver receives a data packet with a protocol type for
- which you specified the default protocol handler, but there is no ERead function
- pending, the .ENET driver discards the packet.
-
- You can have several asynchronous calls to the ERead function pending execution
- simultaneously, as long as you use a different parameter block for each call.
-
- Listing 29-9 defines a completion routine.
-
- Listing 29-9. Using the Default Ethernet Protocol Handler to Read Data (TO BE
- PROVIDED)
-
- _______________________________________________________________________________
-
- æKY Using…Your…Own…Ethernet…Protocol…Handler…to…Read…Data
- æC »Using Your Own Ethernet Protocol Handler to Read Data AppleTalk Manager
- _______________________________________________________________________________
-
- If a client of the .ENET driver has used the EAttachPH function to provide a
- pointer to its own protocol handler, the .ENET driver calls that protocol
- handler, which must in turn call the .ENET driver’s ReadPacket and ReadRest
- routines to read the data. Your protocol handler calls the .ENET driver’s
- ReadPacket and ReadRest routines in essentially the same way as you call the
- .MPP drivers ReadPacket and ReadRest routines (see the AppleTalk Manager chapter
- of Volume II). The following sections describe the .ENET driver’s call to a
- custom protocol handler and the ReadPacket and ReadRest routines.
-
- Note: Because an Ethernet protocol handler must read from and write to the
- CPU’s registers, you cannot write a protocol handler in Pascal.
- _______________________________________________________________________________
-
- æKY How…the….ENET…Driver…Calls…Your…Protocol…Handler
- æC »How the .ENET Driver Calls Your Protocol Handler AppleTalk Manager
- _______________________________________________________________________________
-
- You can provide an Ethernet protocol handler for a particular protocol type and
- use the EAttachPH function to attach it to the .ENET driver. When the driver
- receives an Ethernet packet, it reads the packet header into an internal buffer,
- reads the protocol type, and calls the protocol handler for that protocol type.
- The CPU is in interrupt mode and the registers are used as follows:
-
- Registers on call to Ethernet protocol handler
-
- A0
- Reserved for internal use by the .ENET driver; you must preserve this register
- until after the ReadRest routine has completed execution
-
- A1
- Reserved for internal use by the .ENET driver; you must preserve this register
- until after the ReadRest routine has completed execution
-
- A2 Free for your use
-
- A3
- Pointer to first byte past data-link header bytes (the first byte after the
- 2-byte protocol-type field)
-
- A4
- Pointer to the ReadPacket routine; the ReadRest routine starts 2 bytes after the
- start of the ReadPacket routine
-
- A5
- Free for your use until after the ReadRest routine has completed execution
-
- D0 Free for your use
-
- D1
- Number of bytes in the Ethernet packet left to be read (that is, the number of
- bytes following the Ethernet header)
-
- D2 Free for your use
-
- D3 Free for your use
-
- If your protocol handler processes more than one protocol type, you can read the
- protocol-type field in the data-link header to determine the protocol type of
- the packet. The protocol-type field starts 2 bytes before the address pointed to
- by the A3 register.
-
- Note: The source address starts 8 bytes before the address pointed to by the A3
- register and the destination address starts 14 bytes before the address pointed
- to by the A3 register.
-
- If you know that the packet contains pad bytes and you know the actual size of
- the data, you can reduce the number in the D1 register by the number of pad
- bytes so that the .ENET driver can keep accurate track of the number of bytes
- remaining to be read. In all other circumstances, you should not change the
- value in the D1 register.
-
- After you have called the ReadRest routine, you can use registers A0 through A3
- and D0 through D3 for your own use, and must preserve all other registers. You
- cannot depend on having access to your application global variables.
-
- _______________________________________________________________________________
-
- æKY How…Your…Protocol…Handler…Calls…the….ENET…Driver
- æC »How Your Protocol Handler Calls the .ENET Driver AppleTalk Manager
- _______________________________________________________________________________
-
- Your protocol handler must call the .ENET driver routines ReadPacket and
- ReadRest to read the incoming data packet. You may call the ReadPacket routine
- as many times as you like to read the data piece-by-piece into one or more data
- buffers, but you must always use the ReadRest routine to read the final piece of
- the data packet. The ReadRest routine restores the machine state (the stack
- pointers, status register, and so forth) and checks for error conditions.
- Before you call the ReadPacket routine, you must allocate memory for a data
- buffer and place a pointer to the buffer in the A3 register. You place the
- number of bytes you want to read in the D3 register. You must not request more
- bytes than remain in the data packet.
-
- To call the ReadPacket routine, execute a JSR instruction to the address in the
- A4 register. The ReadPacket routine uses the registers as follows:
-
- Registers on entry to the ReadPacket routine
-
- A3 Pointer to a buffer to hold the data you want to read
- D3 Number of bytes to read; must be nonzero
-
- Registers on exit from the ReadPacket routine
-
- A0 Unchanged
- A1 Unchanged
- A2 Unchanged
- A3 Pointer to next byte to read (first byte after the last byte read)
- D0 Changed
- D1 Number of bytes left to be read
- D2 Unchanged
- D3 Equals 0 if requested number of bytes were read, nonzero if error
-
- The ReadPacket routine indicates an error by clearing to 0 the zero (z) flag in
- the status register. If the ReadPacket routine returns an error, you must
- terminate execution of your protocol handler with an RTS instruction without
- calling ReadPacket again or calling ReadRest at all.
-
- Call the ReadRest routine to read the last portion of the data packet, or call
- it after you have read all the data with ReadPacket routines and before you do
- any other processing or terminate execution. You must provide in the A3 register
- a pointer to a data buffer and must indicate in the D3 register the size of the
- data buffer. If you have already read all of the data with calls to the
- ReadPacket routine, you can specify a 0-size buffer.
-
- † Warning: If you do not call the ReadRest routine after your last call to the
- ReadPacket routine, the system will crash. Ê
-
- To call the ReadRest routine, execute a JSR instruction to an address 2 bytes
- past the address in the A4 register. The ReadRest routine uses the registers as
- follows:
-
- Registers on entry to the ReadRest routine
-
- A3 Pointer to a buffer to hold the data you want to read
- D3 Size of the buffer (word length); may be 0
-
- Registers on exit from the ReadRest routine
-
- A0 Unchanged
- A1 Unchanged
- A2 Unchanged
- A3 Pointer to first byte after the last byte read
- D0 Changed
- D1 Changed
- D2 Unchanged
- D3 Equals 0 if requested number of bytes were read; less than 0 if there was
- more data left than would fit in buffer (extra data equals –D3 bytes); greater
- than 0 if there was less data left than the size of the buffer (extra buffer
- space equals D3 bytes)
-
- If the buffer you provide is not large enough to hold the remaining bytes in the
- packet, the ReadRest routine returns an error. The ReadRest routine indicates an
- error by clearing to 0 the zero (z) flag in the status register.
-
- You must terminate execution of your protocol handler with an RTS instruction
- whether or not the ReadRest routine returns an error.
-
- _______________________________________________________________________________
-
- æKY ENET…Driver…Routines
- æC »ENET Driver Routines AppleTalk Manager
- _______________________________________________________________________________
-
- An application that uses AppleTalk Manager routines for network communications
- can talk to whatever network the user has selected through the Network control
- panel. However, you can choose to write an application that talks only to
- Ethernet; in this case, your application has to address the Ethernet driver
- directly. This section describes the functions that you can use to control the
- .ENET driver, the Ethernet driver provided with system software version 7.0.
- Each.ENET driver function is of the form
-
- FUNCTION Efunc (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
-
- where the thePBptr parameter is a pointer to the .ENET parameter block and the
- async parameter is a Boolean that specifies whether the function is to be
- executed synchronously or asynchronously. Set the async parameter to TRUE to
- execute the function asynchronously.
-
- The .ENET parameter block is defined as follows:
-
- EParamBlock = PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: INTEGER; {queue type}
- ioTrap: INTEGER; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OsErr; {result code}
- ioNamePtr: StringPtr; {driver name}
- ioVRefNum: INTEGER; {volume reference number}
- ioCRefNum: INTEGER; {driver reference number}
- csCode: INTEGER; {primary command code}
-
- CASE INTEGER OF
- EWrite,
- EAttachPH,
- EDetachPH,
- ERead,
- ERdCancel,
- EGetInfo,
- ESetGeneral:
- (
- EProtType: INTEGER; {Ethernet protocol type}
- EPointer: Ptr; {pointer; use depends on function}
- EBuffSize INTEGER {buffer size}
- EDataSize INTEGER {number of bytes read}
- );
-
- EAddMulti,
- EDelMulti:
- (
- EMultiAddr: ?????; {Multicast address}
- );
- END;
-
- The qLink, qType, ioTrap, ioCmdAddr, ioNamePtr, and ioVRefNum fields are
- standard parameters provided by the Pascal or C interface; your application
- should not have to set or read these parameters. The ioResult parameter returns
- the result of the function; in the case that you call the function
- asynchronously, the function sets this field to 1 as soon as it begins
- execution, and changes the field to the actual result code when it completes
- execution. The ioCompletion parameter is a pointer to a completion routine that
- you can provide; the Device Manager calls your completion routine when it
- completes execution of the function. If you are not providing a completion
- routine, specify NIL for this field. The ioCRefNum and csCode fields specify the
- driver and the command to be executed; the MPW Pascal interface fills in these
- fields for you. The Control function is discussed in the Device Manager chapter
- of Volume II.
-
- The remaining parameters are used only for specific functions; all of these
- parameters are described in the following sections.
-
- For a general discussion of the use of the Ethernet driver, see “The .ENET
- Driver” earlier in this chapter.
-
- _______________________________________________________________________________
-
- æKY Attaching…and…Detaching…an…Ethernet…Protocol…Handler
- æC »Attaching and Detaching an Ethernet Protocol Handler AppleTalk Manager
- _______________________________________________________________________________
-
- The functions in this section allow you to attach a protocol handler to the
- .ENET driver, to specify which protocol handler the .ENET driver is to use for
- each protocol type, and to detach a protocol handler that you previously
- attached. The section “Using Your Own Ethernet Protocol Handler to Read Data”
- earlier in this chapter, describes how to write and use Ethernet protocol
- handlers.
-
- FUNCTION EAttachPH (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always EAttachPH
- Æ 28 EProtType word Ethernet protocol type
- Æ 30 EPointer pointer pointer to protocol handler
-
- The EAttachPH function serves two purposes: You can use it to attach to the
- .ENET driver your own protocol handler for a specific protocol type; or you can
- use it to specify that the .ENET driver should use the default protocol handler
- for a particular protocol type. If you attach your own protocol handler, the
- .ENET driver calls that protocol handler each time it receives a packet with the
- protocol type you specified. If you specify that the .ENET driver should use the
- default protocol handler, then you can use the ERead command to read packets
- with that protocol type.
-
- The ioResult parameter returns the result of the function; if you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and changes the field to the actual result code when it completes
- execution. The csCode parameter is a routine selector that is set automatically
- for you by the MPW interface; it is always equal to EAttachPH for this function.
- You specify the protocol type in the EProtType parameter and provide a pointer
- to the protocol handler in the EPointer parameter. If you specify NIL for the
- EPointer parameter, then the .ENET driver uses the default protocol handler for
- that protocol type. Specify 0 for the EProtType parameter to attach a protocol
- handler for the IEEE 802.3 protocol, which uses protocol types 0 through $5DC.
-
- Note: In addition to using the EAttachPH function to install a protocol handler
- for an Ethernet protocol type, you can use the L802Attach function to install a
- protocol handler for an 802.2 protocol type. In the case of an 802.2 protocol
- packet, the .ENET driver passes the packet to the LAP Manager 802.2 protocol
- handler. If the packet has the protocol type you specified with the L802Attach
- function, the 802.2 protocol handler passes the packet on to your protocol
- handler. See “The LAP Manager 802.2 Protocol” earlier in this chapter, for more
- information about IEEE 802.2 protocols.
-
- Result codes
- noErr 0 no error
- LAPProtErr –94 protocol handler is already attached or node’s protocol
- table is full
-
- FUNCTION EDetachPH (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always EDetachPH
- Æ 28 EProtType word Ethernet protocol type
-
- The EDetachPH function detaches a protocol handler from the .ENET driver. Once
- you have removed a protocol type from the node’s protocol table with this
- command, the .ENET driver no longer delivers packets with that protocol type.
- You specify the protocol type in the EProtType parameter.
-
- The ioResult parameter returns the result of the function; if you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and changes the field to the actual result code when it completes
- execution. The csCode parameter is a routine selector that is set automatically
- for you by the MPW interface; it is always equal to EAttachPH for this function.
-
- Result codes
- noErr 0 no error
- LAPProtErr –94 no protocol handler attached
- _______________________________________________________________________________
-
- æKY Writing…and…Reading…Packets…Using…the…Default…Protocol…Handler
- æC »Writing and Reading Packets Using the Default Protocol Handler AppleTalk Manager
- _______________________________________________________________________________
-
- FUNCTION EWrite (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always EWrite
- Æ 30 EPointer pointer pointer to write-data structure
-
- The EWrite function uses the .ENET driver to send a data packet over Ethernet.
- You must first prepare a write-data structure, which specifies the destination
- address and the protocol type and contains the data that you want to send. You
- place a pointer to the write-data structure in the EPointer parameter. If you
- want to send a packet larger than 768 bytes, you must first call the ESetGeneral
- command to put the .ENET driver in general transmission mode. If the size of the
- packet you provide is less than 60 bytes, the driver adds pad bytes to the
- packet. Write-data structures are described in “Using a Write-Data Structure to
- Transmit Ethernet Data” earlier in this chapter.
-
- The ioResult parameter returns the result of the function; if you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and changes the field to the actual result code when it completes
- execution. The csCode parameter is a routine selector that is set automatically
- for you by the MPW interface; it is always equal to EWrite for this function.
-
- Result codes
- noErr 0 no error
- elenErr packet too large or first write-data-structure entry did
- not contain the full 14-byte header
- excessCollsns –95 hardware error
-
- FUNCTION ERead (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always ERead
- Æ 28 EProtType word Ethernet protocol type
- Æ 30 EPointer pointer pointer to data buffer
- Æ 34 EBuffSize word size of data buffer
- ¨ 36 EDataSize word number of bytes read
-
- The ERead function uses the default protocol handler to read a data packet and
- place it in a data buffer. You can use the ERead function to read packets of a
- particular protocol type only after you have used the EAttachPH function to
- specify a NIL pointer to the protocol handler for that protocol type.
-
- The ioResult parameter returns the result of the function; if you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and changes the field to the actual result code when it completes
- execution. The csCode parameter is the routine selector, automatically set by
- the MPW interface. It is always ERead for this function. The ccbRefNum parameter
- is the connection control block reference number that was returned by the
- dspInit command.
-
- The EProtType parameter specifies the protocol type of the packet you want to
- read. The EPointer parameter is a pointer to the data buffer into which you want
- to read data, and the EBuffSize parameter indicates the size of the data buffer.
- If you are expecting EtherTalk data packets, the buffer should be at least 617
- bytes in size; if you are expecting general Ethernet data packets, the buffer
- should be at least 1514 bytes in size.
-
- The ERead function places the entire packet—including the packet header—into
- your buffer. The function returns in the EDataSize parameter the number of bytes
- actually read. If the packet is larger than the data buffer, the ERead function
- places as much of the packet as will fit into the buffer and returns the
- buf2SmallErr result code.
-
- Call the ERead function asynchronously to await the next data packet. When the
- .ENET driver receives the data packet, it completes execution of the ERead
- function and calls your completion routine. If the .ENET driver receives a data
- packet with a protocol type for which you specified the default protocol
- handler, but there is no ERead command pending, the driver discards the data
- packet.
-
- You can have several asynchronous calls to the ERead function pending execution
- simultaneously, as long as you use a different parameter block for each call.
-
- Result codes
- noErr 0 no error
- LAPProtErr –94 protocol not attached or protocol handler pointer was not 0
- buf2SmallErr –3101 packet too large for buffer; partial data returned
- reqAborted –1105 ERdCancel function called for this ERead
-
- FUNCTION ERdCancel (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always ERdCancel
- Æ 30 EPointer pointer pointer to ERead parameter block
-
- The ERdCancel function cancels execution of a specific call to the ERead
- function. You must have called the ERead function asynchronously to use the
- ERdCancel function. You specify in the EPointer parameter a pointer to the
- parameter block that you used when you called the ERead function.
- The ioResult parameter returns the result of the function; if you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and changes the field to the actual result code when it completes
- execution. The csCode parameter is the routine selector, automatically set by
- the MPW interface. It is always ERdCancel for this function. The ccbRefNum
- parameter is the connection control block reference number that was returned by
- the dspInit command.
-
- Result codes
- noErr 0 no error
- CBNotFound –1102 ERead not active
-
- FUNCTION EGetInfo (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always EGetInfo
- Æ 30 EPointer pointer pointer to buffer
- Æ 34 EBuffSize word size of buffer
-
- The EGetInfo function returns information about the .ENET driver. Before calling
- this function, you must allocate a data buffer of at least 18 bytes. Put a
- pointer to the buffer in the EPointer parameter and the size of the buffer in
- the EBuffSize parameter.
-
- The EGetInfo function places the following information in the data buffer:
-
- Bytes Information
-
- 1–6 Ethernet address of the node on which the driver is installed
- 7–10 Number of times the receive buffer has overflowed
- 11–14 Number of data transmission operations that have timed out
- 15–18 Number of packets received that contain an incorrect address
-
- The ioResult parameter returns the result of the function; if you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and changes the field to the actual result code when it completes
- execution. The csCode parameter is the routine selector, automatically set by
- the MPW interface. It is always EGetInfo for this function. The ccbRefNum
- parameter is the connection control block reference number that was returned by
- the dspInit command.
-
- Result code
- noErr 0 no error
-
- FUNCTION ESetGeneral (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always ESetGeneral
-
- The ESetGeneral function switches the .ENET driver from limited-transmission
- mode to general-transmission mode. In limited-transmission mode, the .ENET
- driver allocates a write-data buffer of 768 bytes. This buffer size is more than
- sufficient to hold an EtherTalk data packet, which can be no larger than 617
- bytes. In general-transmission mode, the .ENET driver can transmit an Ethernet
- data packet of up to 1514 bytes.
-
- The ioResult parameter returns the result of the function; if you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and changes the field to the actual result code when it completes
- execution. The csCode parameter is the routine selector, automatically set by
- the MPW interface. It is always ESetGeneral for this function. The ccbRefNum
- parameter is the connection control block reference number that was returned by
- the dspInit command.
-
- There is no command to switch the .ENET driver from general-transmission mode to
- limited-transmission mode. To switch back to limited-transmission mode, you have
- to reset the driver by restarting the computer.
-
- Result codes
- noErr 0 no error
- _______________________________________________________________________________
-
- æKY Adding…and…Removing…Ethernet…Multicast…Addresses
- æC »Adding and Removing Ethernet Multicast Addresses AppleTalk Manager
- _______________________________________________________________________________
-
- FUNCTION EAddMulti (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always EAddMulti
- Æ 28 EMultiAddr 6 bytes multicast address
-
- The EAddMulti function adds a multicast address to the node on which the .ENET
- driver is running. A multicast address is an Ethernet address for which the node
- accepts packets just as it does to its permanently assigned Ethernet hardware
- address. In a muticast address, the low-order bit of the high-order byte is set
- to 1. Each node can have any number of multicast addresses, and any number of
- nodes can have the same multicast address. The purpose of a multicast address is
- to allow a group of Ethernet nodes to receive the same transmission
- simultaneously, in a fashion similar to the AppleTalk broadcast service.
-
- You must provide (in the EMultiAddr parameter) the multicast address that you
- want to use. Each time a client of the .ENET driver calls the EAddMulti function
- for a particular multicast address, the driver increments a counter for that
- multicast address. Each time a client of the .ENET driver calls the EDelMulti
- function, the driver decrements the counter for that address. As long as the
- count for a multicast address is equal to or greater than 1, the .ENET driver
- accepts packets directed to that multicast address. If any client of the .ENET
- driver in the node has called the EAddMulti function for a particular multicast
- address, therefore, the driver receives packets delivered to that address.
-
- The ioResult parameter returns the result of the function; if you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and changes the field to the actual result code when it completes
- execution. The csCode parameter is the routine selector, automatically set by
- the MPW interface. It is always EAddMulti for this function. The ccbRefNum
- parameter is the connection control block reference number that was returned by
- the dspInit command.
-
- Result codes
- noErr 0 no error
- eMultiErr invalid address or table is full
-
- FUNCTION EDelMulti (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always EDelMulti
- Æ 28 EMultiAddr 6 bytes multicast address
-
- The EDelMulti function decrements the counter kept by the .ENET driver for a
- particular multicast address. Each time a client of the .ENET driver calls the
- EAddMulti function, the driver increments a counter for the multicast address
- specified by the EMultiAddr parameter. Each time a client of the .ENET driver
- calls the EDelMulti function, the driver decrements the counter for the address
- specified by the EMultiAddr parameter. As long as the count for a multicast
- address is equal to or greater than 1, the .ENET driver accepts packets directed
- to that multicast address. When the count for an address equals 0, the driver
- removes that address from the list of multicast addresses that it accepts.
-
- Note: Because more than one client of the .ENET driver might be using a
- particular multicast address, you should call the EDelMulti function only once
- for each time you called the EAddMulti function.
-
- The ioResult parameter returns the result of the function; if you call the
- function asynchronously, the function sets this field to 1 as soon as it begins
- execution, and changes the field to the actual result code when it completes
- execution. The csCode parameter is the routine selector, automatically set by
- the MPW interface. It is always EDelMulti for this function. The ccbRefNum
- parameter is the connection control block reference number that was returned by
- the dspInit command.
-
- Result codes
- noErr 0 no error
- eMultiErr address not found
- _______________________________________________________________________________
-
- æKY Summary…of…the…AppleTalk…Manager…Vol…VI
- æC »SUMMARY OF THE APPLETALK MANAGER AppleTalk Manager
- _______________________________________________________________________________
-
- The following cards summarize the constants, data types, and routines for the
- AppleTalk Manager.
- _______________________________________________________________________________
-
- æKY AppleTalk…Constants
- æC »Constants AppleTalk Manager
- _______________________________________________________________________________
-
- CONST
- {csCodes for new .XPP driver routines}
- xCall = 246;
-
- {xppSubCodes}
- getLocalZones = 5;
- getZoneList = 6;
- getMyZone = 7;
-
-
- {driver control csCodes}
- dspInit = 255; {create a new connection end}
- dspRemove = 254; {remove a connection end}
- dspOpen = 253; {open a connection}
- dspClose = 252; {close a connection}
- dspCLInit = 251; {create a connection listener}
- dspCLRemove = 250; {remove a connection listener}
- dspCLListen = 249; {post a listener request}
- dspCLDeny = 248; {deny an open connection request}
- dspStatus = 247; {get status of connection end}
- dspRead = 246; {read data from the connection}
- dspWrite = 245; {write data on the connection}
- dspAttention = 244; {send an attention message}
- dspOptions = 243; {set connection end options}
- dspReset = 242; {forward reset the connection}
- dspNewCID = 241; {generate a cid for a connection end}
-
- {connection opening modes}
- ocRequest = 1; {request a connection with remote}
- ocPassive = 2; {wait for a connection request from remote}
- ocAccept = 3; {accept request as delivered by listener}
- ocEstablish = 4; {consider connection to be open}
-
- {connection end states}
- sListening = 1; {for connection listeners}
- sPassive = 2; {waiting for a connection request from remote}
- sOpening = 3; {requesting a connection with remote}
- sOpen = 4; {connection is open}
- sClosing = 5; {connection is being torn down}
- sClosed = 6; {connection end state is closed}
-
- {client event flags}
- eClosed = $80; {received connection closed advice}
- eTearDown = $40; {closed due to broken connection}
- eAttention = $20; {received attention message}
- eFwdReset = $10; {received forward reset advice}
-
- {miscellaneous constants}
- attnBufSize = 570; {size of client attention buffer}
- minDSPQueueSize = 100; {Minimum size of receive or send Queue}
- _______________________________________________________________________________
-
- æKY AppleTalk…Data…Types
- æC »Data Types AppleTalk Manager
- _______________________________________________________________________________
-
- TYPE ATQentry = RECORD
- qLink: ATQentryPtr; {next queue entry}
- qType: INTEGER; {unused}
- CallAddr: ProcPtr {pointer to your routine}
- END;
-
- ATQentryptr = ^ATQentry;
-
- TPCCB = ^TRCCB;
-
- TRCCB = PACKED RECORD
- ccbLink: TPCCB; {link to next CCB}
- refNum: INTEGER; {user reference number}
- state: INTEGER; {state of the connection end}
- userFlags: Byte; {user flags for connection}
- localSocket: Byte; {local socket number}
- remoteAddress: AddrBlock; {remote end internet address}
- attnCode: INTEGER; {attention code received}
- attnSize: INTEGER; {size of attention data}
- attnPtr: Ptr; {pointer to attention data}
- reserved: PACKED ARRAY [1..220] OF Byte {reserved for use by ADSP}
- END;
-
- AddrBlock = PACKED RECORD
- aNet: INTEGER; {network number}
- aNode: Byte; {node ID}
- aSocket: Byte {socket number}
- END;
-
- DSPParamBlock = PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: INTEGER; {queue type}
- ioTrap: INTEGER; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OSErr; {result code}
- ioNamePtr: StringPtr; {used only for Open routine}
- ioVRefNum: INTEGER; {volume reference number}
- ioCRefNum: INTEGER; {driver reference number}
- csCode: INTEGER; {primary command code}
- qStatus: LONGINT; {reserved for ADSP}
- ccbRefNum: INTEGER; {CCB reference number}
- CASE INTEGER OF
- dspInit,
- dspCLInit:
- (
- ccbPtr: TPCCB; {pointer to CCB}
- userRoutine: ProcPtr; {pointer to user routine}
- sendQSize: INTEGER; {size of send queue}
- sendQueue: Ptr; {pointer to send queue}
- recvQSize: INTEGER; {size of receive queue}
- recvQueue: Ptr; {pointer to receive queue}
- attnPtr: Ptr; {pointer to attention-message buffer}
- localSocket: Byte; {local socket number}
- );
-
- dspOpen,
- dspCLListen,
- dspCLDeny:
- (
- localCID: INTEGER; {local connection ID}
- remoteCID: INTEGER; {remote connection ID}
- remoteAddress: AddrBlock; {remote internet address}
- filterAddress: AddrBlock; {address filter}
- sendSeq: LONGINT; {send sequence number}
- sendWindow: INTEGER; {size of remote buffer}
- recvSeq: LONGINT; {receive sequence number}
- attnSendSeq: LONGINT; {attention send seq number}
- attnRecvSeq: LONGINT; {attention receive seq num}
- ocMode: Byte; {connection opening mode}
- ocInterval: Byte; {interval bet open requests}
- ocMaximum: Byte; {retries of open conn req}
- );
-
- dspClose,
- dspRemove:
- (
- abort: Byte; {abort send requests}
- );
-
- dspStatus:
- (
- statusCCB: TPCCB; {pointer to CCB}
- sendQPending: INTEGER; {bytes waiting in send queue}
- sendQFree: INTEGER; {available send-queue buffer}
- recvQPending: INTEGER; {bytes in receive queue}
- recvQFree: INTEGER; {avail receive-queue buffer}
- )
-
- dspRead,
- dspWrite:
- (
- reqCount: INTEGER; {requested number of bytes}
- actCount: INTEGER; {actual number of bytes}
- dataPtr: Ptr; {pointer to data buffer}
- eom: Byte; {1 if end of message}
- flush: Byte; {1 to send data now}
- )
-
- dspAttention:
- (
- attnCode: INTEGER; {client attention code}
- attnSize: INTEGER; {size of attention data}
- attnData: Ptr; {pointer to attention data}
- attnInterval: Byte; {reserved}
- )
-
- dspOptions:
- (
- sendBlocking: INTEGER; {send-blocking threshold}
- sendTimer: Byte; {reserved}
- rtmtTimer: Byte; {reserved}
- badSeqMax: Byte; {retransmit advice threshold}
- useCheckSum: Byte; {DDP checksum for packets}
- )
-
- dspNewCID:
- (
- newCID: INTEGER; {new connection ID}
- )
- END;
-
- xCallParam = PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: INTEGER; {queue type}
- ioTrap: INTEGER; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OsErr; {result code}
- ioNamePtr: StringPtr; {used only for Open routine}
- ioVRefNum: INTEGER; {volume reference number}
- ioRefNum: INTEGER; {driver reference number}
- csCode: INTEGER; {primary command code}
- xppSubCode: INTEGER; {secondary command code}
- xppTimeOut: Byte; {timeout period for .XPP}
- xppRetry: Byte; {retry count}
- filler: INTEGER; {reserved}
- zipBuffPtr: Ptr; {returned zone names}
- zipNumZones: INTEGER; {number of zones returned}
- zipLastFlag: Byte; {nonzero when all zone names have been returned}
- filler: Byte; {reserved}
- zipInfoField: packed array[1..70] of Byte
- {reserved for use by .XPP}
- END;
-
- XCallParamPtr = ^XCallParam;
- EParamBlock = PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: INTEGER; {queue type}
- ioTrap: INTEGER; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OsErr; {result code}
- ioNamePtr: StringPtr; {driver name}
- ioVRefNum: INTEGER; {volume reference number}
- ioCRefNum: INTEGER; {driver reference number}
- csCode: INTEGER; {primary command code}
-
- CASE INTEGER OF
- EWrite,
- EAttachPH,
- EDetachPH,
- ERead,
- ERdCancel,
- EGetInfo,
- ESetGeneral:
-
- (
- EProtType: INTEGER; {Ethernet protocol type}
- EPointer: Ptr; {pointer; use depends on }
- { function}
- EBuffSize INTEGER {buffer size}
- EDataSize INTEGER {number of bytes read}
- );
-
- EAddMulti,
- EDelMulti:
-
- (
- EMultiAddr: ?????; {Multicast address}
- );
- END;
- _______________________________________________________________________________
-
- æKY AppleTalk…Routines
- æC »Routines AppleTalk Manager
- _______________________________________________________________________________
-
- Getting Information About the .MPP Driver
-
- FUNCTION PGetAppleTalkInfo (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always PGetAppleTalkInfo
- Æ 28 version word version of function
- ¨ 30 varsPtr pointer pointer to MPP globals
- ¨ 34 dcePtr pointer pointer to DCE for .MPP
- ¨ 38 portID word port number
- ¨ 40 configuration long configuration flags
- ¨ 44 selfSend word nonzero if self-send is enabled
- ¨ 46 netLo word low value of the network range
- ¨ 48 netHi word high value of the network range
- ¨ 50 ourAddr long local 24-bit AppleTalk address
- ¨ 54 routerAddr long 24-bit address of router
- ¨ 58 numOfPHs word max number of protocol handlers
- ¨ 60 numOfSkts word max number of static sockets
- ¨ 62 numNBPEs word max concurrent NBP requests
- ¨ 64 ntQueue pointer pointer to registered name queue
- ´ 68 laLength word length in bytes of data link address
- (extended networks only)
- Æ 70 linkAddr pointer pointer to data link address buffer
- (extended networks only)
- Æ 74 zoneName pointer pointer to zone name buffer
-
- Adding and Removing AppleTalk Transition Queue Entries
-
- PROCEDURE LAPAddATQ (entryPtr: pointer);
- PROCEDURE LAPRmvATQ (entryPtr: pointer);
- PROCEDURE LAPGetATQ (VAR eqPtr: pointer);
-
- Sending Messages to the AppleTalk Transition Queue
-
- FUNCTION PATalkClosePrep (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- Æ 26 csCode word always PATalkClosePrep
- Æ appName pointer buffer for name of application that
- denies request
-
- FUNCTION PCancelATClosePrep (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- Æ 26 csCode word always PCancelATClosePrep
-
- Attaching and Detaching 802.2 Protocol Handlers
-
- FUNCTION L802Attach (Eref: word; handlerPtr: procptr;
- ProtType: pointer) : OSErr;
- FUNCTION L802Detach (Eref: word; ProtType: pointer) : OSErr;
-
- Canceling Asynchronous Calls to the ATPKillAllGetReq Function
-
- FUNCTION ATPKillAllGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- Æ 26 csCode word always ATPKillAllGetReq
- Æ 28 atpSocket byte socket for which to cancel all calls
- to ATPGetRequest
-
- Using the .XPP Driver to Obtain Zone Information
-
- FUNCTION GetMyZone (thePBptr:XCallParamPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word routine selector; always xCall
- Æ 28 xppSubCode word routine selector; getMyZone
- Æ 30 xppTimeOut byte retry interval in seconds
- Æ 31 xppRetry byte retry count
- Æ 34 zipBuffPtr long pointer to data buffer
- Æ 42 zipInfoField 70 bytes for use by ZIP; first word set to 0
-
- FUNCTION GetLocalZones (thePBptr:XCallParamPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word routine selector; always xCall
- Æ 28 xppSubCode word routine selector; getLocalZones
- Æ 30 xppTimeOut byte retry interval in seconds
- Æ 31 xppRetry byte retry count
- Æ 34 zipBuffPtr pointer pointer to data buffer
- ¨ 38 zipNumZones word number of names returned
- ¨ 40 zipLastFlag byte nonzero if no more names
- Æ 42 zipInfoField 70 bytes for use by ZIP; first word set to 0
-
- FUNCTION GetZoneList (thePBptr:XCallParamPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word routine selector; always xCall
- Æ 28 xppSubCode word routine selector; getZoneList
- Æ 30 xppTimeOut byte retry interval in seconds
- Æ 31 xppRetry byte retry count
- Æ 34 zipBuffPtr pointer pointer to data buffer
- ¨ 38 zipNumZones word number of names returned
- ¨ 40 zipLastFlag byte nonzero if no more names
- Æ 42 zipInfoField 70 bytes for use by ZIP; first word set to 0
-
- Attaching and Detaching an Ethernet Protocol Handler
-
- FUNCTION EAttachPH (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always EAttachPH
- Æ 28 EProtType word Ethernet protocol type
- Æ 30 EPointer pointer pointer to protocol handler
-
- FUNCTION EDetachPH (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always EDetachPH
- Æ 28 EProtType word Ethernet protocol type
-
- Writing and Reading Ethernet Packets Using the Default Protocol Handler
-
- FUNCTION EWrite (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always EWrite
- Æ 30 EPointer pointer pointer to write-data structure
-
- FUNCTION ERead (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always ERead
- Æ 28 EProtType word Ethernet protocol type
- Æ 30 EPointer pointer pointer to data buffer
- Æ 34 EBuffSize word size of data buffer
- ¨ 36 EDataSize word number of bytes read
-
- FUNCTION ERdCancel (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always ERdCancel
- Æ 30 EPointer pointer pointer to ERead parameter block
-
- FUNCTION EGetInfo (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always EGetInfo
- Æ 30 EPointer pointer pointer to buffer
- Æ 34 EBuffSize word size of buffer
-
- FUNCTION ESetGeneral (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always ESetGeneral
-
- Adding and Removing Ethernet Multicast Addresses
-
- FUNCTION EAddMulti (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always EAddMulti
- Æ 28 EMultiAddr 6 bytes multicast address
-
- FUNCTION EDelMulti (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- ¨ 16 ioResult word result code
- Æ 26 csCode word always EDelMulti
- Æ 28 EMultiAddr 6 bytes multicast address
- _______________________________________________________________________________
-
- æKY AppleTalk…Result…codes
- æC »Result codes AppleTalk Manager
- _______________________________________________________________________________
-
- eMultiErr invalid address or table is full
- elenErr packet too large or first write-data-structure entry
- did not contain the full 14-byte header
- noErr 0 no error
- closeErr –24 permission to close .MPP driver was denied
- ddpSktErr –91 error opening socket
- noBridgeErr –93 no router is available
- LAPProtErr –94 protocol handler is already attached or node’s protocol
-
- table is full
- LAPProtErr –94 no protocol handler attached
- LAPProtErr –94 protocol not attached or protocol handler pointer was
- not 0
- excessCollsns –95 hardware error
- reqFailed –1096 request to contact router failed; retry count exceeded
- cbNotFound –1102 control block not found; no pending asynchronous calls
- CBNotFound –1102 ERead not active
- reqAborted –1105 ERdCancel function called for this ERead
- errDSPQueueSize –1274 send or receive queue is too small
- errFwdReset –1275 read terminated by forward reset
- errAttention –1276 attention message too long
- errOpening –1277 attempt to open connection failed
- errState –1278 bad connection state for this operation
- errAborted –1279 request aborted by dspRemove or dspClose command
- errRefNum –1280 bad connection reference number
- buf2SmallErr –3101 packet too large for buffer; partial data returned
- _______________________________________________________________________________
-
- æKY Assembly-language…Information…for…AppleTalk
- æC »Assembly-language Information AppleTalk Manager
- _______________________________________________________________________________
-
- Constants
-
- mainVersion EQU 1
- subVersion EQU 1
- ;client control codes
- dspInit EQU 255 ;create a new connection end
- dspRemove EQU 254 ;remove a connection end
- dspOpen EQU 253 ;open a connection
- dspClose EQU 252 ;close a connection
- dspCLInit EQU 251 ;create a connection listener
- dspCLRemove EQU 250 ;remove a connection listener
- dspCLListen EQU 249 ;post a listener request
- dspCLDeny EQU 248 ;deny an open connection request
- dspStatus EQU 247 ;get status of connection end
- dspRead EQU 246 ;read data from the connection
- dspWrite EQU 245 ;write data on the connection
- dspAttention EQU 244 ;send an attention message
- dspOptions EQU 243 ;set connection end options
- dspReset EQU 242 ;forward reset the connection
- dspNewCID EQU 241 ;generate a cid for a connection end
- ;open connection modes
- ocRequest EQU 1 ;request a connection with remote
- ocPassive EQU 2 ;wait for a connection request from remote
- ocAccept EQU 3 ;accept request as delivered by listener
- ocEstablish EQU 4 ;consider connection to be open
- ;connection states
- sListening EQU 1 ;for connection listeners
- sPassive EQU 2 ;waiting for a connection request from remote
- sOpening EQU 3 ;requesting a connection with remote
- sOpen EQU 4 ;connection is open
- sClosing EQU 5 ;connection is being torn down
- sClosed EQU 6 ;connection end state is closed
- ;client event flags (bit-mask)
- eClosed EQU $80 ;received connection closed advice
- eTearDown EQU $40 ;closed due to broken connection
- eAttention EQU $20 ;received attention message
- eFwdReset EQU $10 ;received forward reset advice
- ;miscellaneous equates
- attnBufSize EQU 570 ;size of client attention message
- minDSPQueueSize EQU 100 ;minimum size for both receive and send queues
- ;connection control block equates & size
- ccbLink EQU 0 ;link to next ccb
- refNum EQU ccbLink+4 ;user reference number
- state EQU refNum+2 ;state of the connection end
- userFlags EQU state+2 ;flags for unsolicited connection events
- localSocket EQU userFlags+1 ;socket number of this connection end
- remoteAddress EQU localSocket+1 ;internet address of remote end
- attnCode EQU remoteAddress+4 ;attention code received
- attnSize EQU attnCode+2 ;size of received attention data
- attnPtr EQU attnSize+2 ;ptr to received attention data
- ccbSize EQU attnPtr+224 ;total byte size of ccb
- ;adsp queue element equates & size
- csQStatus EQU CSParam ;adsp internal use
- csCCBRef EQU csQStatus+4 ;refnum of ccb
- ;dspInit, dspCLInit
- csCCBPtr EQU csCCBRef+2 ;pointer to connection control block
- csUserRtn EQU csCCBPtr+4 ;client routine to call on event
- csSendQSize EQU csUserRtn+4 ;size of send queue (0..64K bytes)
- csSendQueue EQU csSendQSize+2 ;client passed send queue buffer
- csRecvQSize EQU csSendQueue+4 ;size of receive queue (0..64 KBb)
- csRecvQueue EQU csRecvQSize+2 ;client passed receive queue buffer
- csAttnPtr EQU csRecvQueue+4 ;client passed receive attention buffer
- csLocSkt EQU csAttnPtr+4 ;local socket number
- ;dspOpen, dspCLListen, dspCLDeny
- csLocCID EQU csCCBRef+2 ;local connection id
- csRemCID EQU csLocCID+2 ;remote connection id
- csRemAddr EQU csRemCID+2 ;address of remote end
- csFltrAddr EQU csRemAddr+4 ;address filter
- csSendSeq EQU csFltrAddr+4 ;local send sequence number
- csSendWdw EQU csSendSeq+4 ;send window size
- csRecvSeq EQU csSendWdw+2 ;receive sequence number
- csAttnSendSeq EQU csRecvSeq+4 ;attention send sequence number
- csAttnRecvSeq EQU csAttnSendSeq+4 ;attention receive sequence number
- csOCMode EQU csAttnRecvSeq+4 ;open connection mode
- csOCInterval EQU csOCMode+1 ;open connection request retry interval
- csOCMaximum EQU csOCInterval+1 ;open connection request retry maximum
- ;dspClose, dspRemove
- csAbort EQU csCCBRef+2 ;abort connection immediately if non-zero
- ;dspStatus
- csSQPending EQU csCCBPtr+4 ;pending bytes in send queue
- csSQFree EQU csSQPending+2 ;available buffer space in send queue
- csRQPending EQU csSQFree+2 ;pending bytes in receive queue
- csRQFree EQU csRQPending+2 ;available buffer space in receive queue
- ;dspRead, dspWrite
- csReqCount EQU csCCBRef+2 ;requested number of bytes
- csActCount EQU csReqCount+2 ;actual number of bytes
- csDataPtr EQU csActCount+2 ;pointer to data buffer
- csEOM EQU csDataPtr+4 ;indicates logical end of message
- csFlush EQU csEOM+1 ;send data now dspAttention
- csAttnCode EQU csCCBRef+2 ;client attention code
- csAttnSize EQU csAttnCode+2 ;size of attention data
- csAttnData EQU csAttnSize+2 ;pointer to attention data
- csAttnInterval EQU csAttnData+4 ;retransmit timer in 10-tick intervals
- ;dspOptions
- csSendBlocking EQU csCCBRef+2 ;quantum for data packets
- csSendTimer EQU csSendBlocking+2 ;send timer in 10-tick intervals
- csRtmtTimer EQU csSendTimer+1 ;retransmit timer in 10-tick intervals
- csBadSeqMax EQU csRtmtTimer+1 ;threshold for sending retransmit advice
- csUseCheckSum EQU csBadSeqMax+1 ;use ddp packet checksum dspNewCID
- csNewCID EQU csCCBRef+2 ;new connection id returned
- dspPBSize EQU 68 ;byte size of largest DSP param block
- _______________________________________________________________________________
-
-
- æKY About…The…AppleTalkManager…Chapter
- æC »ABOUT THIS CHAPTER AppleTalkManager
- _______________________________________________________________________________
-
- The AppleTalk Manager is an interface to a pair of RAM device drivers that allow
- Macintosh programs to send and receive information via an AppleTalk network. This
- chapter describes the AppleTalk Manager in detail.
-
- The AppleTalk Manager has been enhanced through the implementation of new protocols
- and an increase in the functionality of the existing interface.
-
- Reader’s guide: The AppleTalk Manager provides services that allow Macintosh
- programs to interact with clients in devices connected to an
- AppleTalk network. Hence you need the information in this
- chapter only if your application uses AppleTalk.
-
- The following is a brief summary of the changes that have been made to the AppleTalk
- Manager interface.
-
- • New parameter block–style Pascal calls have been added for the entire
- AppleTalk Manager. These new calls give the application programmer
- better control of AppleTalk operation within an application.
- • At open time, the .MPP driver can be told to pick a node number in
- the server range. This is a more time consuming but more thorough
- operation than is selecting a node number in the workstation range,
- and it is required for devices acting as servers.
- • Multiple concurrent NBP requests are now supported (just as multiple
- concurrent ATP requests have been supported). The KillNBP command
- has been implemented to abort an outstanding NBP request.
- • ATP requests can now be sent through client-specified sockets, instead
- of having ATP pick the socket itself.
- • The ability to send packets to one’s own node is supported (although
- this functionality is, in the default case, disabled).
- • Two new ATP abort calls have been added: KillSendReq and KillGetReq.
- KillSendReq is functionally equivalent to RelTCB, although its
- arguments are different. KillGetReq is a new call for aborting
- outstanding GetRequests.
- • Additional machine-dependent resources have been added to support,
- for example, more dynamic sockets and more concurrent ATP requests.
- • A new protocol called the Echo Protocol (EP) is supported.
- • A new driver, .XPP, has been added. The .XPP driver implements the
- workstation side of the AppleTalk Session Protocol (ASP) and a small
- portion of the AppleTalk Filing Protocol.
-
- To determine if your application is running on a machine that supports these enhanced
- features, check the version number of the .MPP driver (at offset DCtlQueue+1 in the
- Device Control Entry). A version number of 48 (NCVersion) or greater indicates the
- presence of the new drivers.
-
- You should already be familiar with:
-
- • events, as discussed in the Toolbox Event Manager chapter
- • interrupts and the use of devices and device drivers, as described in
- the Device Manager chapter, if you want to write your own assembly-
- language additions to the AppleTalk Manager
- • the Inside AppleTalk manual, if you want to understand AppleTalk
- protocols in detail
-
- _______________________________________________________________________________
-
-
- æKY AppleTalk…Protocols
- æC »APPLETALK PROTOCOLS AppleTalkManager
- _______________________________________________________________________________
-
- The AppleTalk Manager provides a variety of services that allow Macintosh programs to
- interact with programs in devices connected to an AppleTalk network. This interaction,
- achieved through the exchange of variable-length blocks of data (known as packets)
- over AppleTalk, follows well-defined sets of rules known as protocols.
-
- Although most programmers using AppleTalk needn’t understand the details of these
- protocols, they should understand the information in this section—what the services
- provided by the different protocols are, and how the protocols are interrelated.
- Detailed information about AppleTalk protocols is available in Inside AppleTalk.
-
- The AppleTalk system architecture consists of a number of protocols arranged in
- layers. Each protocol in a specific layer provides services to higher-level layers
- (known as the protocol’s clients) by building on the services provided by lower-level
- layers. A Macintosh program can use services provided by any of the layers in order
- to construct more sophisticated or more specialized services. Figure 1 shows the
- AppleTalk Protocols and their corresponding network layers.
-
- The AppleTalk Manager contains the following protocols:
-
- • AppleTalk Link Access Protocol
- • Datagram Delivery Protocol
- • Routing Table Maintenance Protocol
- • Name-Binding Protocol
- • AppleTalk Transaction Protocol
-
- The following protocols have been added to the AppleTalk Manager:
-
- • Echo Protocol
- • AppleTalk Session Protocol (workstation side)
- • AppleTalk Filing Protocol (small portion of the workstation side)
-
- In Figure 1, the lines indicate the interaction between the protocols. Notice that
- like the Routing Table Maintenance Protocol, the Echo Protocol is not directly accessible
- to Macintosh programs.
-
- The details of these protocols are provided in Inside AppleTalk.
-
- •••Refer to Figure 1.•••
-
- Figure 1–AppleTalk Protocols and OSI Network Layers
-
- Figure 2 illustrates the Macintosh AppleTalk Drivers and the layered structure of the
- protocols which are accessible through each driver. Note that the Routing Table
- Maintenance Protocol isn’t directly accessible to Macintosh Programs.
-
- •••Refer to Figure 2.•••
-
- Figure 2–Macintosh AppleTalk Drivers
-
- The AppleTalk Link Access Protocol (ALAP) provides the lowest-level services of the
- AppleTalk system. Its main function is to control access to the AppleTalk network
- among various competing devices. Each device connected to an AppleTalk network, known
- as a node, is assigned an eight-bit node ID number that identifies the node. ALAP
- ensures that each node on an AppleTalk network has a unique node ID, assigned dynamically
- when the node is started up.
-
- ALAP provides its clients with node-to-node delivery of data frames on a single
- AppleTalk network. An ALAP frame is a variable-length packet of data preceded and
- followed by control information referred to as the ALAP frame header and frame trailer,
- respectively. The ALAP frame header includes the node IDs of the frame’s destination
- and source nodes. The AppleTalk hardware uses the destination node ID to deliver the
- frame. The frame’s source node ID allows a program in the receiving node to determine
- the identity of the source. A sending node can ask ALAP to send a frame to all nodes
- on the AppleTalk network; this broadcast service is obtained by specifying a destination
- node ID of 255.
-
- ALAP can have multiple clients in a single node. When a frame arrives at a node, ALAP
- determines which client it should be delivered to by reading the frame’s ALAP protocol
- type. The ALAP protocol type is an eight-bit quantity, contained in the frame’s
- header, that identifies the ALAP client to whom the frame will be sent. ALAP calls
- the client’s protocol handler, which is a software process in the node that reads in
- and then services the frames. The protocol handlers for a node are listed in a protocol
- handler table.
-
- An ALAP frame trailer contains a 16-bit frame check sequence generated by the AppleTalk
- hardware. The receiving node uses the frame check sequence to detect transmission
- errors, and discards frames with errors. In effect, a frame with an error is “lost”
- in the AppleTalk network, because ALAP doesn’t attempt to recover from errors by
- requesting the sending node to retransmit such frames. Thus ALAP is said to make a
- “best effort” to deliver frames, without any guarantee of delivery.
-
- An ALAP frame can contain up to 600 bytes of client data. The first two bytes must be
- an integer equal to the length of the client data (including the length bytes themselves).
-
- Datagram Delivery Protocol (DDP) provides the next-higher level protocol in the
- AppleTalk architecture, managing socket-to-socket delivery of datagrams over AppleTalk
- internets. DDP is an ALAP client, and uses the node-to-node delivery service provided
- by ALAP to send and receive datagrams. Datagrams are packets of data transmitted by
- DDP. A DDP datagram can contain up to 586 bytes of client data. Sockets are logical
- entities within the nodes of a network; each socket within a given node has a unique
- eight-bit socket number.
-
- On a single AppleTalk network, a socket is uniquely identified by its AppleTalk
- address—its socket number together with its node ID. To identify a socket in the
- scope of an AppleTalk internet, the socket’s AppleTalk address and network number are
- needed. Internets are formed by interconnecting AppleTalk networks via intelligent
- nodes called bridges. A network number is a 16-bit number that uniquely identifies a
- network in an internet. A socket’s AppleTalk address together with its network number
- provide an internet-wide unique socket identifier called an internet address.
-
- Sockets are owned by socket clients, which typically are software processes in the
- node. Socket clients include code called the socket listener, which receives and
- services datagrams addressed to that socket. Socket clients must open a socket before
- datagrams can be sent or received through it. Each node contains a socket table that
- lists the listener for each open socket.
-
- A datagram is sent from its source socket through a series of AppleTalk networks,
- being passed on from bridge to bridge, until it reaches its destination network. The
- ALAP in the destination network then delivers the datagram to the node containing the
- destination socket. Within that node the datagram is received by ALAP calling the DDP
- protocol handler, and by the DDP protocol handler in turn calling the destination
- socket listener, which for most applications will be a higher-level protocol such as
- the AppleTalk Transaction Protocol.
-
- Bridges on AppleTalk internets use the Routing Table Maintenance Protocol (RTMP) to
- maintain routing tables for routing datagrams through the internet. In addition,
- nonbridge nodes use RTMP to determine the number of the network to which they’re
- connected and the node ID of one bridge on their network. The RTMP code in nonbridge
- nodes contains only a subset of RTMP (the RTMP stub), and is a DDP client owning
- socket number 1 (the RTMP socket).
-
- Socket clients are also known as network-visible entities, because they’re the primary
- accessible entities on an internet. Network-visible entities can choose to identify
- themselves by an entity name, an identifier of the form
-
- object:type@zone
-
- Each of the three fields of this name is an alphanumeric string of up to 32 characters.
- The object and type fields are arbitrary identifiers assigned by a socket client, to
- provide itself with a name and type descriptor (for example, abs:Mailbox). The zone
- field identifies the zone in which the socket client is located; a zone is an arbitrary
- subset of AppleTalk networks in an internet. A socket client can identify itself by
- as many different names as it chooses. These aliases are all treated as independent
- identifiers for the same socket client.
-
- The Name-Binding Protocol (NBP) maintains a names table in each node that contains
- the name and internet address of each entity in that node. These name-address pairs
- are called NBP tuples. The collection of names tables in an internet is known as the
- names directory.
-
- NBP allows its clients to add or delete their name-address tuples from the
- node’s names table. It also allows its clients to obtain the internet addresses of
- entities from their names. This latter operation, known as name lookup (in the names
- directory), requires that NBP install itself as a DDP client and broadcast special
- name-lookup packets to the nodes in a specified zone. These datagrams are sent by NBP
- to the names information socket—socket number 2 in every node using NBP.
-
- NBP clients can use special meta-characters in place of one or more of the three
- fields of the name of an entity it wishes to look up. The character “=” in the object
- or type field signifies “all possible values”. The zone field can be replaced by “*”,
- which signifies “this zone”—the zone in which the NBP client’s node is located. For
- example, an NBP client performing a lookup with the name
-
- =:Mailbox@*
-
- will obtain in return the entity names and internet addresses of all mailboxes in the
- client’s zone (excluding the client’s own names and addresses). The client can specify
- whether one or all of the matching names should be returned.
-
- NBP clients specify how thorough a name lookup should be by providing NBP with the
- number of times (retry count) that NBP should broadcast the lookup packets and the
- time interval (retry interval) between these retries.
-
- As noted above, ALAP and DDP provide “best effort” delivery services with no recovery
- mechanism when packets are lost or discarded because of errors. Although for many
- situations such a service suffices, the AppleTalk Transaction Protocol (ATP) provides
- a reliable loss-free transport service. ATP uses transactions, consisting of a transaction
- request and a transaction response, to deliver data reliably. Each transaction is
- assigned a 16-bit transaction ID number to distinguish it from other transactions. A
- transaction request is retransmitted by ATP until a complete response has been received,
- thus allowing for recovery from packet-loss situations. The retry interval and retry
- count are specified by the ATP client sending the request.
-
- Although transaction requests must be contained in a single datagram, transaction
- responses can consist of as many as eight datagrams. Each datagram in a response is
- assigned a sequence number from 0 to 7, to indicate its ordering within the response.
-
- ATP is a DDP client, and uses the services provided by DDP to transmit requests and
- responses. ATP supports both at-least-once and exactly-once transactions. Four of the
- bytes in an ATP header, called the user bytes, are provided for use by ATP’s clients—they’re
- ignored by ATP.
-
- ATP’s transaction model and means of recovering from datagram loss are covered in
- detail below.
-
- The Echo Protocol (EP) provides an echoing service through static socket number 4
- known as the echoer socket. The echoer listens for packets received through this
- socket. Any correctly formed packet sent to the echoer socket on a node will be
- echoed back to its sender.
-
- This simple protocol can be used for two important purposes:
-
- • EP can be used by any Datagram Delivery Protocol (DDP) client to
- determine if a particular node (known to have an echoer) is accessible
- over an internet.
- • EP is useful in determining the average time it takes for a packet to
- travel to a remote node and back. This is very helpful in developing
- client-dependent heuristics for estimating the timeouts to be specified
- by clients of ATP, ASP, and other protocols.
-
- Programs cannot access EP directly via the AppleTalk Manager. The EP implementation
- exists solely to respond to EP requests sent by other nodes. EP is a DDP client
- residing on statically-assigned socket 4, the echoing socket. Clients wishing to
- send EP requests (and receive EP responses) should use the Datagram Delivery Protocol
- (DDP) to send the appropriate packet. For more information about the EP packet
- format, see Inside AppleTalk.
-
- The AppleTalk Session Protocol (ASP) provides for the setting up, maintaining and
- closing down of a session. A session is a logical relationship between two network
- entities, a workstation and a server. The workstation tells the server what to do,
- and the server responds with the appropriate actions. ASP makes sure that the session
- dialog is maintained in the correct sequence and that both ends of the conversation
- are properly participating.
-
- ASP will generally be used between two communicating network entities where one is
- providing a service to the other (for example, a server is providing a service to a
- workstation) and the service provided is state-dependent. That is, the response to a
- particular request from an entity is dependent upon other previous requests from that
- entity. For example, a request to read bytes from a file is dependent upon a previous
- request to open that file in the first place. However, a request to return the time
- of day is independent of all such previous requests.
-
- When the service provided is state-dependent, requests must be delivered to the
- server in the same order as generated by the workstation. ASP guarantees requests
- are delivered to the server in the order in which they are issued, and that duplicate
- requests are never delivered (another requirement of state-dependent service).
-
- ASP is an asymmetric protocol, providing one set of services to the workstation and a
- different set of services to the server.
-
- ASP workstation clients initiate (open) sessions, send requests (commands) on that
- session, and close sessions down. ASP server clients receive and respond
- (through command replies) to these requests. ASP guarantees that these requests are
- delivered in the same order as they are made, and without duplication. ASP is also
- responsible for closing down the session if one end fails or becomes unreachable, and
- will inform its client (either server or workstation) of the action.
-
- ASP also provides various additional services, such as allowing a workstation to
- obtain server status information without opening a session to a server, writing
- blocks of data from the workstation to the server end of the session, and providing
- the ability for a server to send an attention message to the workstation.
-
- ASP assumes that the workstation client has a mechanism for looking up the network
- address of the server with which it wants to set up a session.
- (Generally this is done using the AppleTalk Name Binding Protocol.)
-
- Both ends of the session periodically check to see that the other end of the session
- is still responsive. If one end fails or becomes unreachable the other end closes
- the session.
-
- ASP is a client of ATP and calls ATP for transport services.
-
- ASP does not
-
- • ensure that consecutive commands complete in the order in which they
- were sent (and delivered) to the server
- • understand or interpret the syntax or the semantics of the commands
- sent to the server by the workstation
- • allow the server to send commands to the workstation (The server
- is allowed to alert the workstation through the server’s attention
- mechanism only.)
-
- Note: The .XPP driver does implement the workstation side of the
- AppleTalk Filing Protocol login command.
-
- The AppleTalk Filing Protocol (AFP) allows a workstation on an AppleTalk network to
- access files on an AFP file server. AFP specifies a remote filing system that provides
- user authentication and an access control mechanism that supports volume and folder-level
- access rights. For details of AFP, refer to Inside AppleTalk.
-
- _______________________________________________________________________________
-
-
- æKY AppleTalk…Transaction…Protocol
- æC »APPLETALK TRANSACTION PROTOCOL AppleTalkManager
- _______________________________________________________________________________
-
- This section covers ATP in greater depth, providing more detail about three of its
- fundamental concepts: transactions, buffer allocation, and recovery of lost datagrams.
-
- _______________________________________________________________________________
-
- »Transactions
-
- A transaction is a interaction between two ATP clients, known as the requester and
- the responder. The requester calls the .ATP driver in its node to send a transaction
- request (TReq) to the responder, and then awaits a response. The TReq is received by
- the .ATP driver in the responder’s node and is delivered to the responder. The responder
- then calls its .ATP driver to send back a transaction response (TResp), which is
- received by the requester’s .ATP driver and delivered to the requester. Figure 3
- illustrates this process.
-
- •••Refer to Figure 3.•••
-
- Figure 3–Transaction Process
-
- Simple examples of transactions are:
-
- • read a counter, reset it and send back the value read
- • read six sectors of a disk and send back the data read
- • write the data sent in the TReq to a printer
-
- A basic assumption of the transaction model is that the amount of ATP data sent in
- the TReq specifying the operation to be performed is small enough to fit in a single
- datagram. A TResp, on the other hand, may span several datagrams, as in the second
- example. Thus, a TReq is a single datagram, while a TResp consists of up to eight
- datagrams, each of which is assigned a sequence number from 0 to 7 to indicate its
- position in the response.
-
- The requester must, before calling for a TReq to be sent, set aside enough buffer
- space to receive the datagram(s) of the TResp. The number of buffers allocated (in
- other words, the maximum number of datagrams that the responder can send) is indicated
- in the TReq by an eight-bit bit map. The bits of this bit map are numbered 0 to 7
- (the least significant bit being number 0); each bit corresponds to the response
- datagram with the respective sequence number.
-
- _______________________________________________________________________________
-
- »Datagram Loss Recovery
-
- The way that ATP recovers from datagram loss situations is best explained by an
- example; see Figure 4. Assume that the requester wants to read six sectors of 512
- bytes each from the responder’s disk. The requester puts aside six 512-byte buffers
- (which may or may not be contiguous) for the response datagrams, and calls ATP to
- send a TReq. In this TReq the bit map is set to binary 00111111 or decimal 63. The
- TReq carries a 16-bit transaction ID, generated by the requester’s .ATP driver before
- sending it. (This example assumes that the requester and responder have already
- agreed that each buffer can hold 512
- bytes.) The TReq is delivered to the responder, which reads the six disk sectors and
- sends them back, through ATP, in TResp datagrams bearing sequence numbers 0 through
- 5. Each TResp datagram also carries exactly the same transaction ID as the TReq to
- which they’re responding.
-
- There are several ways that datagrams may be lost in this case. The original TReq
- could be lost for one of many reasons. The responding node might be too busy to
- receive the TReq or might be out of buffers for receiving it, there could be an
- undetected collision on the network, a bit error in the transmission line, and so on.
- To recover from such errors, the requester’s .ATP driver maintains an ATP retry timer
- for each transaction sent. If this timer expires and the complete TResp has not been
- received, the TReq is retransmitted and the retry timer is restarted.
-
- A second error situation occurs when one or more of the TResp datagrams isn’t received
- correctly by the requester’s .ATP driver (datagram 1 in Figure 4). Again, the retry
- timer will expire and the complete TResp will not have been received; this will
- result in a retransmission of the TReq. However, to avoid unnecessary retransmission
- of the TResp datagrams already properly received, the bit map of this retransmitted
- TReq is modified to reflect only those datagrams not yet received. Upon receiving
- this TReq, the responder retransmits only the missing response datagrams.
-
- Another possible failure is that the responder’s .ATP driver goes down or the responder
- becomes unreachable through the underlying network system. In this case, retransmission
- of the TReq could continue indefinitely. To avoid this situation, the requester
- provides a maximum retry count; if this count is exceeded, the requester’s .ATP
- driver returns an appropriate error message to the requester.
-
- •••Refer to Figure 4.•••
-
- Figure 4–Datagram Loss Recovery
-
- Note: There may be situations where, due to an anticipated delay, you’ll
- want a request to be retransmitted more than 255 times; specifying a
- retry count of 255 indicates “infinite retries” to ATP and will cause
- a message to be retransmitted until the request has either been
- serviced, or been cancelled through a specific call.
- _______________________________________________________________________________
-
- »THE APPLETALK MANAGER
- _______________________________________________________________________________
-
- Finally, in our example, what if the responder is able to provide only four disk
- sectors (having reached the end of the disk) instead of the six requested? To handle
- this situation, there’s an end-of-message (EOM) flag in each TResp datagram. In this
- case, the TResp datagram numbered 3 would come with this flag set. The reception of
- this datagram informs the requester’s .ATP driver that TResps numbered 4 and 5 will
- not be sent and should not be expected.
-
- When the transaction completes successfully (all expected TResp datagrams are received
- or TResp datagrams numbered 0 to n are received with datagram n’s EOM flag set), the
- requester is informed and can then use the data received in the TResp.
-
- ATP provides two classes of service: at-least-once (ALO) and exactly-once (XO). The
- TReq datagram contains an XO flag that’s set if XO service is required and cleared if
- ALO service is adequate. The main difference between the two is in the sequence of
- events that occurs when the TReq is received by the responder’s .ATP driver.
-
- In the case of ALO service, each time a TReq is received (with the XO flag cleared),
- it’s delivered to the responder by its .ATP driver; this is true even for retransmitted
- TReqs of the same transaction. Each time the TReq is delivered, the responder performs
- the requested operation and sends the necessary TResp datagrams. Thus, the requested
- operation is performed at least once, and perhaps several times, until the transaction
- is completed at the requester’s end.
-
- The at-least-once service is satisfactory in a variety of situations—for instance, if
- the requester wishes to read a clock or a counter being maintained at the responder’s
- end. However, in other circumstances, repeated execution of the requested operation
- is unacceptable. This is the case, for instance, if the requester is sending data to
- be printed at the responding end; exactly-once service is designed for such situations.
-
- The responder’s .ATP driver maintains a transactions list of recently received XO
- TReqs. Whenever a TReq is received with its XO flag set, the driver goes through this
- list to see if this is a retransmitted TReq. If it’s the first TReq of a transaction,
- it’s entered into the list and delivered to the responder. The responder executes the
- requested operation and calls its driver to send a TResp. Before sending it out, the
- .ATP driver saves the TResp in the list.
-
- When a retransmitted TReq for the same XO transaction is received, the responder’s
- .ATP driver will find a corresponding entry in the list. The retransmitted TReq is
- not delivered to the responder; instead, the driver automatically retransmits the
- response datagrams that were saved in the list. In this way, the responder never sees
- the retransmitted TReqs and the requested operation is performed only once.
-
- ATP must include a mechanism for eventually removing XO entries from the responding
- end’s transaction list; two provisions are made for this. When the requester’s .ATP
- driver has received all the TResp datagrams of a particular transaction, it sends a
- datagram known as a transaction release (TRel); this tells the responder’s .ATP
- driver to remove the transaction from the list. However, the TRel could be lost in
- the network (or the responding end may die, and so on), leaving the entry in the list
- forever. To account for this situation, the responder’s .ATP driver maintains a
- release timer for each transaction. If this timer expires and no activity has occurred
- for the transaction, its entry is removed from the transactions list.
-
- _______________________________________________________________________________
-
-
- æKY About…the…AppleTalk…Manager
- æC »ABOUT THE APPLETALK MANAGER AppleTalkManager
- _______________________________________________________________________________
-
- The AppleTalk Manager is divided into three parts (see Figure 5):
-
- • A lower-level driver called “.MPP” that contains code to implement ALAP,
- DDP, NBP, and the RTMP stub; this includes separate code resources loaded
- in when an NBP name is registered or looked up.
- • A higher-level driver called “.ATP” that implements ATP.
- • A Pascal interface to these two drivers, which is a set of Pascal data
- types and routines to aid Pascal programmers in calling the AppleTalk
- Manager.
-
- •••Refer to Figure 5.•••
-
- Figure 5–Calling the AppleTalk Manager
-
- The two drivers and the interface to them are not in ROM; your application must link
- to the appropriate object files.
-
- Pascal programmers make calls to the AppleTalk Manager’s Pascal interface, which in
- turn makes Device Manager Control calls to the two drivers. Assembly-language programmers
- make Device Manager Control calls directly to the drivers.
-
- Note: Pascal programmers can, of course, make PBControl calls directly
- if they wish.
-
- The AppleTalk Manager provides ALAP routines that allow a program to:
-
- • send a frame to another node
- • receive a frame from another node
- • add a protocol handler to the protocol handler table
- • remove a protocol handler from the protocol handler table
-
- Each node may have up to four protocol handlers in its protocol handler table, two of
- which are currently used by DDP.
-
- By calling DDP, socket clients can:
-
- • send a datagram via a socket
- • receive a datagram via a socket
- • open a socket and add a socket listener to the socket table
- • close a socket and remove a socket listener from the socket table
-
- Each node may have up to 12 open sockets in its socket table.
-
- Programs cannot access RTMP directly via the AppleTalk Manager; RTMP exists solely
- for the purpose of providing DDP with routing information.
-
- The NBP code allows a socket client to:
-
- • register the name and socket number of an entity in the node’s names table
- • determine the address (and confirm the existence) of an entity
- • delete the name of an entity from the node’s names table
-
- The AppleTalk Manager’s .ATP driver allows a socket client to do the following:
-
- • open a responding socket to receive requests
- • send a request to another socket and get back a response
- • receive a request via a responding socket
- • send a response via a responding socket
- • close a responding socket
-
- Note: Although the AppleTalk Manager provides four different protocols
- for your use, you’re not bound to use all of them. In fact, most
- programmers will use only the NBP and ATP protocols.
-
- AppleTalk communicates via channel B of the Serial Communications Controller
- (SCC). When the Macintosh is started up with a disk containing the AppleTalk code,
- the status of serial port B is checked. If port B isn’t being used by another device
- driver, and is available for use by AppleTalk, the .MPP driver is loaded into the
- system heap. On a Macintosh 128K, only the MPP code is loaded at system startup; the
- .ATP driver and NBP code are read into the application heap when the appropriate
- commands are issued. On a Macintosh 512K or XL, all AppleTalk code is loaded into the
- system heap at system startup.
-
- After loading the AppleTalk code, the .MPP driver installs its own interrupt handlers,
- installs a task into the vertical retrace queue, and prepares the SCC for use. It
- then chooses a node ID for the Macintosh and confirms that the node ID isn’t already
- being used by another node on the network.
-
- Warning: For this reason it’s imperative that the Macintosh be connected
- to the AppleTalk network through serial port B (the printer port)
- before being switched on.
-
- The AppleTalk Manager also provides Pascal routines for opening and closing the .MPP
- and .ATP drivers. The open calls allow a program to load AppleTalk code at times
- other than system startup. The close calls allow a program to remove the AppleTalk
- code from the Macintosh; the use of close calls is highly discouraged, since other
- co-resident programs are then “disconnected” from AppleTalk. Both sets of calls are
- described in detail under “Calling the AppleTalk Manager from Pascal”.
-
- Warning: If, at system startup, serial port B isn’t available for use by
- AppleTalk, the .MPP driver won’t open. However, a driver doesn’t
- return an error message when it fails to open. Pascal programmers
- must ensure the proper opening of AppleTalk by calling one of the
- two routines for opening the AppleTalk drivers (either MPPOpen or
- ATPLoad). If AppleTalk was successfully loaded at system startup,
- these calls will have no effect; otherwise they’ll check the
- availability of port B, attempt to load the AppleTalk code, and
- return an appropriate result code.
-
- Assembly-language note: Assembly-language programmers can use the Pascal
- routines for opening AppleTalk. They can also check
- the availability of port B themselves and then decide
- whether to open MPP or ATP. Detailed information on
- how to do this is provided in the section “Calling
- the AppleTalk Manager from Assembly Language”.
-
- The two AppleTalk device drivers, named .MPP and .ATP, are included in the 128K ROM.
- The AppleTalk Manager, however (the interface to the drivers), is not in ROM; your
- application must link to the appropriate object files.
-
- On the Macintosh Plus, you need only open the .MPP driver; this will also load the
- .ATP driver and NBP code automatically. Since, in the 128K ROM, device drivers return
- errors, it’s no longer necessary to check whether port B is free and configured for
- AppleTalk. If port B isn’t available, the .MPP driver won’t open and the result code
- portInUse or portNotCf will be returned.
-
- Assembly-language note: When called from assembly language, the Datagram
- Delivery Protocol (DDP) allows 14 (instead of 12)
- open sockets.
-
- The changes to the AppleTalk manager increase functionality and resources. Two interfaces
- for the AppleTalk Manager calls are discussed: the new or preferred interface and the
- alternate interface. Picking a node address in the server range, sending packets to
- one’s own node, multiple concurrent NBP requests, sending ATP requests through a
- specified socket and two new ATP calls are also discussed in this section. These
- calls can only be made with the preferred interface.
-
- _______________________________________________________________________________
-
-
- æKY Calling…the…AppleTalk…Manager…from…Pascal
- æC »CALLING THE APPLETALK MANAGER FROM PASCAL AppleTalkManager
- _______________________________________________________________________________
-
- This section discusses how to use the AppleTalk Manager from Pascal. Equivalent
- assembly-language information is given in the “Calling the AppleTalk Manager from
- Assembly Language” section.
-
- You can execute many AppleTalk Manager routines either synchronously (meaning that
- the application can’t continue until the routine is completed) or asynchronously
- (meaning that the application is free to perform other tasks while the routine is
- being executed).
-
- When an application calls an AppleTalk Manager routine asynchronously, an I/O request
- is placed in the appropriate driver’s I/O queue, and control returns to the calling
- program—possibly even before the actual I/O is completed. Requests are taken from the
- queue one at a time, and processed; meanwhile, the calling program is free to work on
- other things.
-
- The routines that can be executed asynchronously contain a Boolean parameter called
- async. If async is TRUE, the call is executed asynchronously; otherwise the call is
- executed synchronously. Every time an asynchronous routine call is completed, the
- AppleTalk Manager posts a network event. The message field of the event record will
- contain a handle to the parameter block that was used to make that call.
-
- Most AppleTalk Manager routines return an integer result code of type OSErr. Each
- routine description lists all of the applicable result codes generated by the AppleTalk
- Manager, along with a short description of what the result code means. Lengthier
- explanations of all the result codes can be found in the summary at the end of the
- chapter. Result codes from other parts of the Operating System may also be returned.
- (See Appendix A for a list of all result codes.)
-
- Many Pascal calls to the AppleTalk Manager require information passed in a parameter
- block of type ABusRecord. The exact content of an ABusRecord depends on the protocol
- being called:
-
- TYPE ABProtoType = (lapProto,ddpProto,nbpProto,atpProto);
- ABusRecord = RECORD
- abOpcode: ABCallType; {type of call}
- abResult: INTEGER; {result code}
- abUserReference: LONGINT; {for your use}
- CASE ABProtoType OF
- lapProto:
- . . . {ALAP parameters}
- ddpProto:
- . . . {DDP parameters}
- nbpProto:
- . . . {NBP parameters}
- atpProto:
- . . . {ATP parameters}
- END;
- END;
-
- ABRecPtr = ^ABusRecord;
- ABRecHandle = ^ABRecPtr;
-
- The value of the abOpcode field is inserted by the AppleTalk Manager when the call is
- made, and is always a member of the following set:
-
- TYPE ABCallType = (tLAPRead,tLAPWrite,tDDPRead,tDDPWrite,tNBPLookup,
- tNBPConfirm,tNBPRegister,tATPSndRequest,
- tATPGetRequest,tATPSdRsp,tATPAddRsp,tATPRequest,
- tATPRespond);
-
- The abUserReference field is available for use by the calling program in any way it
- wants. This field isn’t used by the AppleTalk Manager routines or drivers.
-
- The size of an ABusRecord data structure in bytes is given by one of the following
- constants:
-
- CONST lapSize = 20;
- ddpSize = 26;
- nbpSize = 26;
- atpSize = 56;
-
- Variables of type ABusRecord must be allocated in the heap with Memory Manager NewHandle
- calls. For example:
-
- myABRecord := ABRecHandle(NewHandle(ddpSize))
-
- Warning: These Memory Manager calls can’t be made inside interrupts.
-
- Routines that are executed asynchronously return control to the calling program with
- the result code noErr as soon as the call is placed in the driver’s I/O queue. This
- isn’t an indication of successful call completion; it simply indicates that the call
- was successfully queued to the appropriate driver. To determine when the call is
- actually completed, you can either check for a network event or poll the abResult
- field of the call’s ABusRecord. The abResult field, set to 1 when the call is made,
- receives the actual result code upon completion of the call.
-
- Warning: A data structure of type ABusRecord is often used by the AppleTalk
- Manager during an asynchronous call, and so is locked by the
- AppleTalk Manager. Don’t attempt to unlock or use such a variable.
-
- Each routine description includes a list of the ABusRecord fields affected by the
- routine. The arrow next to each field name indicates whether it’s an input, output,
- or input/output parameter:
-
- Arrow Meaning
- --> Parameter is passed to the routine
- <-- Parameter is returned by the routine
- <-> Parameter is passed to and returned by the routine
-
- _______________________________________________________________________________
-
- »Opening and Closing AppleTalk
-
- •••Refer to Technical Note #224:•••
-
- FUNCTION MPPOpen : OSErr; [Not in ROM]
-
- MPPOpen first checks whether the .MPP driver has already been loaded; if it has,
- MPPOpen does nothing and returns noErr. If MPP hasn’t been loaded, MPPOpen attempts
- to load it into the system heap. If it succeeds, it then initializes the driver’s
- variables and goes through the process of dynamically assigning a node ID to that
- Macintosh. On a Macintosh 512K or XL, it also loads the .ATP driver and NBP code into
- the system heap.
-
- If serial port B isn’t configured for AppleTalk, or is already in use, the .MPP
- driver isn’t loaded and an appropriate result code is returned.
-
- Result codes noErr No error
- portInUse Port B is already in use
- portNotCf Port B not configured for AppleTalk
-
- FUNCTION MPPClose : OSErr; [Not in ROM]
-
- MPPClose removes the .MPP driver, and any data structures associated with it, from
- memory. If the .ATP driver or NBP code were also installed, they’re removed as well.
- MPPClose also returns the use of port B to the Serial Driver.
-
- Warning: Since other co-resident programs may be using AppleTalk, it’s
- strongly recommended that you never use this call. MPPClose will
- completely disable AppleTalk; the only way to restore AppleTalk
- is to call MPPOpen again.
-
- _______________________________________________________________________________
-
- »AppleTalk Link Access Protocol
-
- »Data Structures
-
- ALAP calls use the following ABusRecord fields:
-
- lapProto:
- (lapAddress: LAPAdrBlock; {destination or source node ID}
- lapReqCount: INTEGER; {length of frame data or buffer size in bytes}
- lapActCount: INTEGER; {number of frame data bytes actually received}
- lapDataPtr: Ptr); {pointer to frame data or pointer to buffer}
-
- When an ALAP frame is sent, the lapAddress field indicates the ID of the destination
- node. When an ALAP frame is received, lapAddress returns the ID of the source node.
- The lapAddress field also indicates the ALAP protocol type of the frame:
-
- TYPE LAPAdrBlock = PACKED RECORD
- dstNodeID: Byte; {destination node ID}
- srcNodeID: Byte; {source node ID}
- lapProtType: ABByte {ALAP protocol type}
- END;
-
- When an ALAP frame is sent, lapReqCount indicates the size of the frame data in bytes
- and lapDataPtr points to a buffer containing the frame data to be sent. When an ALAP
- frame is received, lapDataPtr points to a buffer in which the incoming data can be
- stored and lapReqCount indicates the size of the buffer in bytes. The number of bytes
- actually sent or received is returned in the lapActCount field.
-
- Each ALAP frame contains an eight-bit ALAP protocol type in the header. ALAP protocol
- types 128 through 255 are reserved for internal use by ALAP, hence the declaration:
-
- TYPE ABByte = 1..127; {ALAP protocol type}
-
- Warning: Don’t use ALAP protocol type values 1 and 2; they’re reserved
- for use by DDP. Value 3 through 15 are reserved for internal
- use by Apple and also shouldn’t be used.
-
- »Using ALAP
-
- Most programs will never need to call ALAP, because higher-level protocols will
- automatically call it as necessary. If you do want to send a frame directly via ALAP,
- call the LAPWrite function. If you want to read ALAP frames, you have two choices:
-
- • Call LAPOpenProtocol with NIL for protoPtr (see below); this installs
- the default protocol handler provided by the AppleTalk Manager. Then
- call LAPRead to receive frames.
- • Write your own protocol handler, and call LAPOpenProtocol to add it
- to the node’s protocol handler table. The ALAP code will examine every
- incoming frame and send all those with the correct ALAP protocol type
- to your protocol handler. See the section “Protocol Handlers and Socket
- Listeners” for information on how to write a protocol handler.
-
- When your program no longer wants to receive frames with a particular ALAP protocol
- type value, it can call LAPCloseProtocol to remove the corresponding protocol handler
- from the protocol handler table.
-
- »ALAP Routines
-
- FUNCTION LAPOpenProtocol (theLAPType: ABByte;
- protoPtr: Ptr) : OSErr; [Not in ROM]
-
- LAPOpenProtocol adds the ALAP protocol type specified by theLAPType to the
- node’s protocol table. If you provide a pointer to a protocol handler in protoPtr,
- ALAP will send each frame with an ALAP protocol type of theLAPType to that protocol
- handler.
-
- If protoPtr is NIL, the default protocol handler will be used for receiving frames
- with an ALAP protocol type of theLAPType. In this case, to receive a frame you must
- call LAPRead to provide the default protocol handler with a buffer for placing the
- data. If, however, you’ve written your own protocol handler and protoPtr points to
- it, your protocol handler will have the responsibility for receiving the frame and
- it’s not necessary to call LAPRead.
-
- Result codes noErr No error
- lapProtErr Error attaching protocol type
-
- FUNCTION LAPCloseProtocol (theLAPType: ABByte) : OSErr; [Not in ROM]
-
- LAPCloseProtocol removes from the node’s protocol table the specified ALAP protocol
- type, as well as its protocol handler.
-
- Warning: Don’t close ALAP protocol type values 1 or 2. If you close these
- protocol types, DDP will be disabled; once disabled, the only way
- to restore DDP is to restart the system, or to close and then
- reopen AppleTalk.
-
- Result codes noErr No error
- lapProtErr Error detaching protocol type
-
- FUNCTION LAPWrite (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tLAPWrite}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> lapAddress.dstNodeID {destination node ID}
- --> lapAddress.lapProtType {ALAP protocol type}
- --> lapReqCount {length of frame data}
- --> lapDataPtr {pointer to frame data}
-
- LAPWrite sends a frame to another node. LAPReqCount and lapDataPtr specify the length
- and location of the data to send. The lapAddress.lapProtType field indicates the ALAP
- protocol type of the frame and the lapAddress.dstNodeID indicates the node ID of the
- node to which the frame should be sent.
-
- Note: The first two bytes of an ALAP frame’s data must contain the length
- in bytes of that data, including the length bytes themselves.
-
- Result codes noErr No error
- excessCollsns Unable to contact destination node;
- packet not sent
- ddpLenErr ALAP data length too big
- lapProtErr Invalid ALAP protocol type
-
- FUNCTION LAPRead (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tLAPRead}
- <-- abResult {result code}
- --> abUserReference {for your use}
- <-- lapAddress.dstNodeID {destination node ID}
- <-- lapAddress.srcNodeID {source node ID}
- --> lapAddress.lapProtType {ALAP protocol type}
- --> lapReqCount {buffer size in bytes}
- <-- lapActCount {number of frame data bytes actually received}
- --> lapDataPtr {pointer to buffer}
-
- LAPRead receives a frame from another node. LAPReqCount and lapDataPtr specify the
- size and location of the buffer that will receive the frame data. If the buffer isn’t
- large enough to hold all of the incoming frame data, the extra bytes will be discarded
- and buf2SmallErr will be returned. The number of bytes actually received is returned
- in lapActCount. Only frames with ALAP protocol type equal to lapAddress.lapProtType
- will be received. The node IDs of the frame’s source and destination nodes are returned
- in lapAddress.srcNodeID and lapAddress.dstNodeID. You can determine whether the
- packet was broadcast to you by examining the value of lapAddress.dstNodeID—if the
- packet was broadcast it’s equal to 255, otherwise it’s equal to your node ID.
-
- Note: You should issue LAPRead calls only for ALAP protocol types that were
- opened (via LAPOpenProtocol) to use the default protocol handler.
-
- Warning: If you close a protocol type for which there are still LAPRead
- calls pending, the calls will be canceled but the memory occupied
- by their ABusRecords will not be released. For this reason, before
- closing a protocol type, call LAPRdCancel to cancel any pending
- LAPRead calls associated with that protocol type.
-
- Result codes noErr No error
- buf2SmallErr Frame too large for buffer
- readQErr Invalid protocol type or protocol type not
- found in table
-
- FUNCTION LAPRdCancel (abRecord: ABRecHandle) : OSErr; [Not in ROM]
-
- Given the handle to the ABusRecord of a previously made LAPRead call, LAPRdCancel
- dequeues the LAPRead call, provided that a packet satisfying the LAPRead has not
- already arrived. LAPRdCancel returns noErr if the LAPRead call is successfully removed
- from the queue. If LAPRdCancel returns recNotFnd, check the abResult field to verify
- that the LAPRead has been completed and determine its outcome.
-
- Result codes noErr No error
- readQErr Invalid protocol type or protocol type not
- found in table
- recNotFnd ABRecord not found in queue
-
- »Example
-
- This example sends an ALAP packet synchronously and waits asynchronously for a response.
- Assume that both nodes are using a known protocol type (in this case, 73) to receive
- packets, and that the destination node has a node ID of 4.
-
- VAR
- myABRecord: ABRecHandle;
- myBuffer: PACKED ARRAY [0..599] OF CHAR; {buffer for both send and receive}
- myLAPType: Byte;
- errCode, index, dataLen: INTEGER;
- someText: Str255;
- async: BOOLEAN;
-
- BEGIN
- errCode := MPPOpen;
- IF errCode <> noErr THEN
- WRITELN('Error in opening AppleTalk')
- {Maybe serial port B isn't available for use by AppleTalk}
- ELSE
- BEGIN
- {Call Memory Manager to allocate ABusRecord}
- myABRecord := ABRecHandle(NewHandle(lapSize));
- myLAPType := 73;
- {Enter myLAPType into protocol handler table and install default handler to }
- { service frames of that ALAP type. No packets of that ALAP type will be }
- { received until we call LAPRead.}
- errCode := LAPOpenProtocol(myLAPType, NIL);
- IF errCode <> noErr THEN
- WRITELN('Error while opening the protocol type')
- {Have we opened too many protocol types? Remember that DDP uses two of }
- { them.}
- ELSE
- BEGIN
- {Prepare data to be sent}
- someText := 'This data will be in the ALAP data area';
- {The .MPP implementation requires that the first two bytes of the ALAP }
- { data field contain the length of the data, including the length bytes }
- { themselves.}
- dataLen := LENGTH(someText) + 2;
- buffer[0] := CHR(dataLen DIV 256); {high byte of data length}
- buffer[1] := CHR(dataLen MOD 256); {low byte of data length}
- FOR index := 1 TO dataLen - 2 DO {stuff buffer with packet data}
- buffer[index + 1] := someText[index];
- async := FALSE;
- WITH myABRecord^^ DO {fill parameters in the ABusRecord}
- BEGIN
- lapAddress.lapProtType := myLAPType;
- lapAddress.dstNodeID := 4;
- lapReqCount := dataLen;
- lapDataPtr := @buffer;
- END;
- {Send the frame}
- errCode := LAPWrite(myABRecord, async);
- {In the case of a sync call, errCode and the abResult field of }
- { the myABRecord will contain the same result code. We can also }
- { reuse myABRecord, since we know whether the call has completed.}
- IF errCode <> noErr THEN
- WRITELN('Error while writing out the packet')
- {Maybe the receiving node wasn't on-line}
- ELSE
- BEGIN
- {We have sent out the packet and are now waiting for a response. We }
- { issue an async LAPRead call so that we don't “hang” waiting for a }
- { response that may not come.}
- async := TRUE;
- WITH myABRecord^^ DO
- BEGIN
- lapAddress.lapProtType := myLAPType;
- {ALAP type we want to receive }
- lapReqCount := 600; {our buffer is maximum size}
- lapDataPtr := @buffer;
- END;
- errCode := LAPRead(myABRecord, async); {wait for a packet}
- IF errCode <> noErr THEN
- WRITELN('Error while trying to queue up a LAPRead')
- {Was the protocol handler installed correctly?}
- ELSE
- BEGIN
- {We can either sit here in a loop and poll the abResult }
- { field or just exit our code and use the event }
- { mechanism to flag us when the packet arrives.}
- CheckForMyEvent; {your procedure for checking for a network event}
- errCode := LAPCloseProtocol(myLAPType);
- IF errCode <> noErr THEN
- WRITELN('Error while closing the protocol type');
- END;
- END;
- END;
- END;
- END.
-
-
- _______________________________________________________________________________
-
- »Datagram Delivery Protocol
-
- »Data Structures
-
- DDP calls use the following ABusRecord fields:
-
- ddpProto:
- (ddpType: Byte; {DDP protocol type}
- ddpSocket: Byte; {source or listening socket number}
- ddpAddress: AddrBlock; {destination or source socket address}
- ddpReqCount: INTEGER; {length of datagram data or buffer size in bytes}
- ddpActCount: INTEGER; {number of bytes actually received}
- ddpDataPtr: Ptr; {pointer to buffer}
- ddpNodeID: Byte); {original destination node ID}
-
- When a DDP datagram is sent, ddpReqCount indicates the size of the datagram data in
- bytes and ddpDataPtr points to a buffer containing the datagram data. DDPSocket
- specifies the socket from which the datagram should be sent. DDPAddress is the internet
- address of the socket to which the datagram should be sent:
-
- TYPE AddrBlock = PACKED RECORD
- aNet: INTEGER; {network number}
- aNode: Byte; {node ID}
- aSocket: Byte {socket number}
- END;
-
- Note: The network number you specify in ddpAddress.aNet tells MPP whether
- to create a long header (for an internet) or a short header (for a
- local network only). A short DDP header will be sent if ddpAddress.aNet
- is 0 or equal to the network number of the local network.
-
- When a DDP datagram is received, ddpDataPtr points to a buffer in which the incoming
- data can be stored and ddpReqCount indicates the size of the buffer in bytes. The
- number of bytes actually sent or received is returned in the ddpActCount field.
- DDPAddress is the internet address of the socket from which the datagram was sent.
-
- DDPType is the DDP protocol type of the datagram, and ddpSocket specifies the socket
- that will receive the datagram.
-
- Warning: DDP protocol types 1 through 15 and DDP socket numbers 1 through 63
- are reserved by Apple for internal use. Socket numbers 64 through 127
- are available for experimental use. Use of these experimental sockets
- isn’t recommended for commercial products, since there’s no mechanism
- for eliminating conflicting usage by different developers.
-
- »Using DDP
-
- Before it can use a socket, the program must call DDPOpenSocket, which adds a socket
- and its socket listener to the socket table. When a program is finished using a
- socket, call DDPCloseSocket, which removes the socket’s entry from the socket table.
- To send a datagram via DDP, call DDPWrite. To receive datagrams, you have two choices:
-
- • Call DDPOpenSocket with NIL for sktListener (see below); this installs
- the default socket listener provided by the AppleTalk Manager. Then call
- DDPRead to receive datagrams.
- • Write your own socket listener and call DDPOpenSocket to install it. DDP
- will call your socket listener for every incoming datagram for that
- socket; in this case, you shouldn’t call DDPRead. For information on how
- to write a socket listener, see the section “Protocol Handlers and Socket
- Listeners”.
-
- To cancel a previously issued DDPRead call (provided it’s still in the queue), call
- DDPRdCancel.
-
- »DDP Routines
-
- FUNCTION DDPOpenSocket (VAR theSocket: Byte;
- sktListener: Ptr) : OSErr; [Not in ROM]
-
- DDPOpenSocket adds a socket and its socket listener to the socket table. If theSocket
- is nonzero, it must be in the range 64 to 127, and it specifies the socket’s number;
- if theSocket is 0, DDPOpenSocket dynamically assigns a socket number in the range 128
- to 254, and returns it in theSocket. SktListener contains a pointer to the socket
- listener; if it’s NIL, the default listener will be used.
-
- If you’re using the default socket listener, you must then call DDPRead to receive a
- datagram (in order to specify buffer space for the default socket listener). If,
- however, you’ve written your own socket listener and sktListener points to it, your
- listener will provide buffers for receiving datagrams and you shouldn’t use DDPRead
- calls.
-
- DDPOpenSocket will return ddpSktErr if you pass the number of an already opened
- socket, if you pass a socket number greater than 127, or if the socket table is
- full.
-
- Note: The range of static socket numbers 1 through 63 is reserved by Apple
- for internal use. Socket numbers 64 through 127 are available for
- unrestricted experimental use.
-
- Result codes noErr No error
- ddpSktErr Socket error
-
- FUNCTION DDPCloseSocket (theSocket: Byte) : OSErr; [Not in ROM]
-
- DDPCloseSocket removes the entry of the specified socket from the socket table and
- cancels all pending DDPRead calls that have been made for that socket. If you pass a
- socket number of 0, or if you attempt to close a socket that isn’t open, DDPCloseSocket
- will return ddpSktErr.
-
- Result codes noErr No error
- ddpSktErr Socket error
-
- FUNCTION DDPWrite (abRecord: ABRecHandle; doChecksum: BOOLEAN;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tDDPWrite}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> ddpType {DDP protocol type}
- --> ddpSocket {source socket number}
- --> ddpAddress {destination socket address}
- --> ddpReqCount {length of datagram data}
- --> ddpDataPtr {pointer to buffer}
-
- DDPWrite sends a datagram to another socket. DDPReqCount and ddpDataPtr specify the
- length and location of the data to send. The ddpType field indicates the DDP protocol
- type of the frame, and ddpAddress is the complete internet address of the socket to
- which the datagram should be sent. DDPSocket specifies the socket from which the
- datagram should be sent. Datagrams sent over the internet to a node on an AppleTalk
- network different from the sending node’s network have an optional software checksum
- to detect errors that might occur inside the intermediate bridges. If doChecksum is
- TRUE, DDPWrite will compute this checksum; if it’s FALSE, this software checksum
- feature is ignored.
-
- Note: The destination socket can’t be in the same node as the program
- making the DDPWrite call.
-
- Result codes noErr No error
- ddpLenErr Datagram length too big
- ddpSktErr Source socket not open
- noBridgeErr No bridge found
-
- FUNCTION DDPRead (abRecord: ABRecHandle; retCksumErrs: BOOLEAN;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tDDPRead}
- <-- abResult {result code}
- --> abUserReference {for your use}
- <-- ddpType {DDP protocol type}
- --> ddpSocket {listening socket number}
- <-- ddpAddress {source socket address}
- --> ddpReqCount {buffer size in bytes}
- <-- ddpActCount {number of bytes actually received}
- --> ddpDataPtr {pointer to buffer}
- <-- ddpNodeID {original destination node ID}
-
- DDPRead receives a datagram from another socket. The size and location of the buffer
- that will receive the data are specified by ddpReqCount and ddpDataPtr. If the buffer
- isn’t large enough to hold all of the incoming frame data, the extra bytes will be
- discarded and buf2SmallErr will be returned. The number of bytes actually received is
- returned in ddpActCount. DDPSocket specifies the socket to receive the datagram (the
- “listening” socket). The node to which the packet was sent is returned in ddpNodeID;
- if the packet was broadcast ddpNodeID will contain 255. The address of the socket
- that sent the packet is returned in ddpAddress. If retCksumErrs is FALSE, DDPRead
- will discard any packets received with an invalid checksum and inform the caller of
- the error. If retCksumErrs is TRUE, DDPRead will deliver all packets, whether or not
- the checksum is valid; it will also notify the caller when there’s a checksum error.
-
- Note: The sender of the datagram must be in a different node from the
- receiver. You should issue DDPRead calls only for receiving datagrams
- for sockets opened with the default socket listener; see the
- description of DDPOpenSocket.
-
- Note: If the buffer provided isn’t large enough to hold all of the incoming
- frame data (buf2SmallErr), the checksum can’t be calculated; in this
- case, DDPRead will deliver packets even if retCksumErrs is FALSE.
-
- Result codes noErr No error
- buf2SmallErr Datagram too large for buffer
- cksumErr Checksum error
- ddpLenErr Datagram length too big
- ddpSktErr Socket error
- readQErr Invalid socket or socket not found in table
-
- FUNCTION DDPRdCancel (abRecord: ABRecHandle) : OSErr; [Not in ROM]
-
- Given the handle to the ABusRecord of a previously made DDPRead call, DDPRdCancel
- dequeues the DDPRead call, provided that a packet satisfying the DDPRead hasn’t
- already arrived. DDPRdCancel returns noErr if the DDPRead call is successfully removed
- from the queue. If DDPRdCancel returns recNotFnd, check the abResult field of abRecord
- to verify that the DDPRead has been completed and determine its outcome.
-
- Result codes noErr No error
- readQErr Invalid socket or socket not found in table
- recNotFnd ABRecord not found in queue
-
- »Example
-
- This example sends a DDP packet synchronously and waits asynchronously for a response.
- Assume that both nodes are using a known socket number (in this case, 30) to receive
- packets. Normally, you would want to use NBP to look up your destination’s socket
- address.
-
- VAR
- myABRecord: ABRecHandle;
- myBuffer: PACKED ARRAY [0..599] OF CHAR; {buffer for both send and receive}
- mySocket: Byte;
- errCode, index, dataLen: INTEGER;
- someText: Str255;
- async, retCksumErrs, doChecksum: BOOLEAN;
-
- BEGIN
- errCode := MPPOpen;
- IF errCode <> noErr THEN
- WRITELN('Error in opening AppleTalk')
- {Maybe serial port B isn't available for use by AppleTalk}
- ELSE
- BEGIN
- {Call Memory Manager to allocate ABusRecord}
- myABRecord := ABRecHandle(NewHandle(ddpSize));
- mySocket := 30;
- {Add mySocket to socket table and install default socket listener to service }
- { datagrams addressed to that socket. No packets addressed to mySocket will be }
- { received until we call DDPRead. }
- errCode := DDPOpenSocket(mySocket, NIL);
- IF errCode <> noErr THEN
- WRITELN('Error while opening the socket')
- {Have we opened too many socket listeners? Remember that DDP uses two of }
- { them.}
- ELSE
- BEGIN
- {Prepare data to be sent}
- someText := 'This is a sample datagram';
- dataLen := LENGTH(someText);
- FOR index := 0 TO dataLen - 1 DO {stuff buffer with packet data}
- myBuffer[index] := someText[index + 1];
- async := FALSE;
- WITH myABRecord^^ DO {fill the parameters in the ABusRecord}
- BEGIN
- ddpType := 5;
- ddpAddress.aNet := 0; {send on “our” network}
- ddpAddress.aNode := 34;
- ddpAddress.aSocket := mySocket;
- ddpReqCount := dataLen;
- ddpDataPtr := @myBuffer;
- END;
- doChecksum := FALSE;
- {If packet contains a DDP long header, compute checksum and insert it into }
- { the header.}
- errCode := DDPWrite(myABRecord, doChecksum, async); {send packet}
- {In the case of a sync call, errCode and the abResult field of myABRecord }
- { will contain the same result code. We can also reuse myABRecord, since we }
- { know whether the call has completed.}
- IF errCode <> noErr THEN
- WRITELN('Error while writing out the packet')
- {Maybe the receiving node wasn't on-line}
- ELSE
- BEGIN
- {We have sent out the packet and are now waiting for a response. We }
- { issue an async DDPRead call so that we don't “hang” waiting for a }
- { response that may not come. To cancel the async read call, we must }
- { close the socket associated with the call or call DDPRdCancel.}
- async := TRUE;
- retCksumErrs := TRUE; {return packets even if }
- { they have a checksum error}
- WITH myABRecord^^ DO
- BEGIN
- ddpSocket := mySocket;
- ddpReqCount := 600; {our reception buffer is max size}
- ddpDataPtr := @myBuffer;
- END;
- {Wait for a packet asynchronously}
- errCode := DDPRead(myABRecord, retCksumErrs, async);
- IF errCode <> noErr THEN
- WRITELN('Error while trying to queue up a DDPRead')
- {Was the socket listener installed correctly?}
- ELSE
- BEGIN
- {We can either sit here in a loop and poll the }
- { abResult field or just exit our code and use the }
- { event mechanism to flag us when the packet arrives.}
- CheckForMyEvent; {your procedure for checking for a }
- { network event}
- {If there were no errors, a packet is inside the array }
- { mybuffer, the length is in ddpActCount, and the }
- { address of the sending socket is in ddpAddress. }
- { Process the packet received here and report any errors.}
- errCode := DDPCloseSocket(mySocket); {we're done with it}
- IF errCode <> noErr THEN
- WRITELN('Error while closing the socket');
- END;
- END;
- END;
- END;
- END.
-
- _______________________________________________________________________________
-
- »AppleTalk Transaction Protocol
-
- »Data Structures
-
- ATP calls use the following ABusRecord fields:
-
- atpProto:
- (atpSocket: Byte; {listening or responding socket number}
- atpAddress: AddrBlock; {destination or source socket address}
- atpReqCount: INTEGER; {request size or buffer size}
- atpDataPtr: Ptr; {pointer to buffer}
- atpRspBDSPtr: BDSPtr; {pointer to response BDS}
- atpBitMap: BitMapType; {transaction bit map}
- atpTransID: INTEGER; {transaction ID}
- atpActCount: INTEGER; {number of bytes actually received}
- atpUserData: LONGINT; {user bytes}
- atpXO: BOOLEAN; {exactly-once flag}
- atpEOM: BOOLEAN; {end-of-message flag}
- atpTimeOut: Byte; {retry timeout interval in seconds}
- atpRetries: Byte; {maximum number of retries}
- atpNumBufs: Byte; {number of elements in response BDS or number }
- { of response packets sent}
- atpNumRsp: Byte; {number of response packets received or }
- { sequence number}
- atpBDSSize: Byte; {number of elements in response BDS}
- atpRspUData: LONGINT; {user bytes sent or received in transaction }
- { response}
- atpRspBuf: Ptr; {pointer to response message buffer}
- atpRspSize: INTEGER); {size of response message buffer}
-
- The socket receiving the request or sending the response is identified by atpSocket.
- ATPAddress is the address of either the destination or the source socket of a transaction,
- depending on whether the call is sending or receiving data, respectively. ATPDataPtr
- and atpReqCount specify the location and size
- (in bytes) of a buffer that either contains a request or will receive a request. The
- number of bytes actually received in a request is returned in atpActCount. ATPTransID
- specifies the transaction ID. The transaction bit map is contained in atpBitMap, in
- the form:
-
- TYPE BitMapType = PACKED ARRAY[0..7] OF BOOLEAN;
-
- Each bit in the bit map corresponds to one of the eight possible packets in a response.
- For example, when a request is made for which five response packets are expected, the
- bit map sent is binary 00011111 or decimal 31. If the second packet in the response
- is lost, the requesting socket will retransmit the request with a bit map of binary
- 00000010 or decimal 2.
-
- ATPUserData contains the user bytes of an ATP header. ATPXO is TRUE if the transaction
- is to be made with exactly-once service. ATPEOM is TRUE if the response packet is the
- last packet of a transaction. If the number of responses is less than the number that
- were requested, then ATPEOM must also be TRUE. ATPNumRsp contains either the number
- of responses received or the sequence number of a response.
-
- The timeout interval in seconds and the maximum number of times that a request should
- be made are indicated by atpTimeOut and atpRetries, respectively.
-
- Note: Setting atpRetries to 255 will cause the request to be retransmitted
- indefinitely, until a full response is received or the call is canceled.
-
- ATP provides a data structure, known as a response buffer data structure
- (response BDS), for allocating buffer space to receive the datagram(s) of the response.
- A response BDS is an array of one to eight elements. Each BDS element defines the
- size and location of a buffer for receiving one response datagram; they’re numbered 0
- to 7 to correspond to the sequence numbers of the response datagrams.
-
- ATP needs a separate buffer for each response datagram expected, since packets may
- not arrive in the proper sequence. It does not, however, require you to set up and
- use the BDS data structure to describe the response buffers; if you
- don’t, ATP will do it for you. Two sets of calls are provided for both requests and
- responses; one set requires you to allocate a response BDS and the other doesn’t.
-
- Assembly-language note: The two calls that don’t require you to define a BDS
- data structure (ATPRequest and ATPResponse) are
- available in Pascal only.
-
- The number of BDS elements allocated (in other words, the maximum number of datagrams
- that the responder can send) is indicated in the TReq by an eight-bit bit map. The
- bits of this bit map are numbered 0 to 7 (the least significant bit being number 0);
- each bit corresponds to the response datagram with the respective sequence number.
-
- ATPRspBDSPtr and atpBDSSize indicate the location and number of elements in the
- response BDS, which has the following structure:
-
- TYPE BDSElement =
- RECORD
- buffSize: INTEGER; {buffer size in bytes}
- buffPtr: Ptr; {pointer to buffer}
- dataSize: INTEGER; {number of bytes actually received}
- userBytes: LONGINT {user bytes}
- END;
-
- BDSType = ARRAY[0..7] OF BDSElement; {response BDS}
- BDSPtr = ^BDSType;
-
- ATPNumBufs indicates the number of elements in the response BDS that contain information.
- In most cases, you can allocate space for your variables of BDSType statically with a
- VAR declaration. However, you can allocate only the minimum space required by your
- ATP calls by doing the following:
-
- VAR myBDSPtr: BDSPtr;
- . . .
- numOfBDS := 3; {number of elements needed}
- myBDSPtr := BDSPtr(NewPtr(SIZEOF(BDSElement) * numOfBDS));
-
- Note: The userBytes field of the BDSElement and the atpUserData field
- of the ABusRecord represent the same information in the datagram.
- Depending on the ATP call made, one or both of these fields will be used.
-
- »Using ATP
-
- Before you can use ATP on a Macintosh 128K, the .ATP driver must be read from the
- system resource file via an ATPLoad call. The .ATP driver loads itself into the
- application heap and installs a task into the vertical retrace queue.
-
- Warning: When another application starts up, the application heap is
- reinitialized; on a Macintosh 128K, this means that the ATP
- code is lost (and must be reloaded by the next application).
-
- When you’re through using ATP on a Macintosh 128K, call ATPUnload—the system will be
- returned to the state it was in before the .ATP driver was opened.
-
- On a Macintosh 512K or XL, the .ATP driver will have been loaded into the system heap
- either at system startup or upon execution of MPPOpen or ATPLoad. ATPUnload has no
- effect on a Macintosh 512K or XL.
-
- To send a transaction request, call ATPSndRequest or ATPRequest. The .ATP driver will
- automatically select and open a socket through which the request datagram will be
- sent, and through which the response datagrams will be received. The requester must
- specify the full network address (network number, node ID, and socket number) of the
- socket to which the request is to be sent. This socket is known as the responding
- socket, and its address must be known in advance by the requester.
-
- At the responder’s end, before a transaction request can be received, a responding
- socket must be opened, and the appropriate calls be made, to receive a request. To do
- this, the responder first makes an ATPOpenSocket call which allows the responder to
- specify the address (or part of it) of the requesters from whom it’s willing to
- accept transaction requests. Then it issues an ATPGetRequest call to provide ATP with
- a buffer for receiving a request; when a request is received, ATPGetRequest is completed.
- The responder can queue up several ATPGetRequest calls, each of which will be completed
- as requests are received.
-
- Upon receiving a request, the responder performs the requested operation, and then
- prepares the information to be returned to the requester. It then calls ATPSndRsp (or
- ATPResponse) to send the response. Actually, the responder can issue the ATPSndRsp
- call with only part (or none) of the response specified. Additional portions of the
- response can be sent later by calling ATPAddRsp.
-
- The ATPSndRsp and ATPAddRsp calls provide flexibility in the design (and range of
- types) of transaction responders. For instance, the responder may, for some reason,
- be forced to send the responses out of sequence. Also, there might be memory constraints
- that force sending the complete transaction response in parts. Even though eight
- response datagrams might need to be sent, the responder might have only enough memory
- to build one datagram at a time. In this case, it would build the first response
- datagram and call ATPSndRsp to send it. It would then build the second response
- datagram in the same buffer and call ATPAddRsp to send it; and so on, for the third
- through eighth response datagrams.
-
- A responder can close a responding socket by calling ATPCloseSocket. This call cancels
- all pending ATP calls for that socket, such as ATPGetRequest, ATPSndRsp, and ATPResponse.
-
- For exactly-once transactions, the ATPSndRsp and ATPAddRsp calls don’t terminate
- until the entire transaction has completed (that is, the responding end receives a
- release packet, or the release timer has expired).
-
- To cancel a pending, asynchronous ATPSndRequest or ATPRequest call, call ATPReqCancel.
- To cancel a pending, asynchronous ATPSndRsp or ATPResponse call, call ATPRspCancel.
- Pending asynchronous ATPGetRequest calls can be canceled only by issuing the ATPCloseSocket
- call, but that will cancel all outstanding calls for that socket.
-
- •••Refer to Technical Note #250:•••
-
- Warning: You cannot reuse a variable of type ABusRecord passed to an ATP
- routine until the entire transaction has either been completed
- or canceled.
-
- »ATP Routines
-
- FUNCTION ATPLoad : OSErr; [Not in ROM]
-
- •••Refer to Technical Note #224:•••
-
- ATPLoad first verifies that the .MPP driver is loaded and running. If it isn’t,
- ATPLoad verifies that port B is configured for AppleTalk and isn’t in use, and then
- loads MPP into the system heap.
-
- ATPLoad then loads the .ATP driver, unless it’s already in memory. On a Macintosh
- 128K, ATPLoad reads the .ATP driver from the system resource file into the application
- heap; on a Macintosh 512K or XL, ATP is read into the system heap.
-
- Note: On a Macintosh 512K or XL, ATPLoad and MPPOpen perform essentially
- the same function.
-
- Result codes noErr No error
- portInUse Port B is already in use
- portNotCf Port B not configured for AppleTalk
-
- FUNCTION ATPUnload : OSErr; [Not in ROM]
-
- ATPUnload makes the .ATP driver purgeable; the space isn’t actually released by the
- Memory Manager until necessary.
-
- Note: This call applies only to a Macintosh 128K; on a Macintosh 512K
- or Macintosh XL, ATPUnload has no effect.
-
- Result codes noErr No error
-
- FUNCTION ATPOpenSocket (addrRcvd: AddrBlock;
- VAR atpSocket: Byte) : OSErr; [Not in ROM]
-
- ATPOpenSocket opens a socket for the purpose of receiving requests. ATPSocket contains
- the socket number of the socket to open; if it’s 0, a number is dynamically assigned
- and returned in atpSocket. AddrRcvd contains a filter of the sockets from which
- requests will be accepted. A 0 in the network number, node ID, or socket number field
- of the addrRcvd record acts as a “wild card”; for instance, a 0 in the socket number
- field means that requests will be accepted from all sockets in the node(s) specified
- by the network and node fields.
-
- Result codes noErr No error
- tooManySkts Socket table full
- noDataArea Too many outstanding ATP calls
-
- Note: If you’re only going to send requests and receive responses to
- these requests, you don’t need to open an ATP socket. When you
- make the ATPSndRequest or ATPRequest call, ATP automatically
- opens a dynamically assigned socket for that purpose.
-
- FUNCTION ATPCloseSocket (atpSocket: Byte) : OSErr; [Not in ROM]
-
- ATPCloseSocket closes the responding socket whose number is specified by atpSocket.
- It releases the data structures associated with all pending, asynchronous calls
- involving that socket; these pending calls are completed immediately and return the
- result code sktClosed.
-
- Result codes noErr No error
- noDataArea Too many outstanding ATP calls
-
- FUNCTION ATPSndRequest (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tATPSndRequest}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> atpAddress {destination socket address}
- --> atpReqCount {request size in bytes}
- --> atpDataPtr {pointer to buffer}
- --> atpRspBDSPtr {pointer to response BDS}
- --> atpUserData {user bytes}
- --> atpXO {exactly-once flag}
- <-- atpEOM {end-of-message flag}
- --> atpTimeOut {retry timeout interval in seconds}
- --> atpRetries {maximum number of retries}
- --> atpNumBufs {number of elements in response BDS}
- <-- atpNumRsp {number of response packets actually received}
-
- ATPSndRequest sends a request to another socket. ATPAddress is the internet address
- of the socket to which the request should be sent. ATPDataPtr and atpReqCount specify
- the location and size of a buffer that contains the request information to be sent.
- ATPUserData contains the user bytes for the ATP header.
-
- ATPSndRequest requires you to allocate a response BDS. ATPRspBDSPtr is a pointer to
- the response BDS; atpNumBufs indicates the number of elements in the BDS (this is
- also the maximum number of response datagrams that will be accepted). The number of
- response datagrams actually received is returned in atpNumRsp; if a nonzero value is
- returned, you can examine the response BDS to determine which packets of the transaction
- were actually received. If the number returned is less than requested, one of the
- following is true:
-
- • Some of the packets have been lost and the retry count has been exceeded.
- • ATPEOM is TRUE; this means that the response consisted of fewer packets
- than were expected, but that all packets sent were received (the last
- packet came with the atpEOM flag set).
-
- ATPTimeOut indicates the length of time that ATPSndRequest should wait for a response
- before retransmitting the request. ATPRetries indicates the maximum number of retries
- ATPSndRequest should attempt. ATPXO should be TRUE if you want the request to be part
- of an exactly-once transaction.
-
- ATPSndRequest completes when either the transaction is completed or the retry count
- is exceeded.
-
- Result codes noErr No error
- reqFailed Retry count exceeded
- tooManyReqs Too many concurrent requests
- noDataArea Too many outstanding ATP calls
-
- FUNCTION ATPRequest (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tATPRequest}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> atpAddress {destination socket address}
- --> atpReqCount {request size in bytes}
- --> atpDataPtr {pointer to buffer}
- <-- atpActCount {number of bytes actually received}
- --> atpUserData {user bytes}
- --> atpXO {exactly-once flag}
- <-- atpEOM {end-of-message flag}
- --> atpTimeOut {retry timeout interval in seconds}
- --> atpRetries {maximum number of retries}
- <-- atpRspUData {user bytes received in transaction response}
- --> atpRspBuf {pointer to response message buffer}
- --> atpRspSize {size of response message buffer}
-
- ATPRequest is functionally analogous to ATPSndRequest. It sends a request to another
- socket, but doesn’t require the caller to set up and use the BDS data structure to
- describe the response buffers. ATPAddress indicates the socket to which the request
- should be sent. ATPDataPtr and atpReqCount specify the location and size of a buffer
- that contains the request information to be sent. ATPUserData contains the user bytes
- to be sent in the request’s ATP header. ATPTimeOut indicates the length of time that
- ATPRequest should wait for a response before retransmitting the request. ATPRetries
- indicates the maximum number of retries ATPRequest should attempt.
-
- To use this call, you must have an area of contiguous buffer space that’s large
- enough to receive all expected datagrams. The various datagrams will be assembled in
- this buffer and returned to you as a complete message upon completion of the transaction.
- The location and size of this buffer are passed in atpRspBuf and atpRspSize. Upon
- completion of the call, the size of the received response message is returned in
- atpActCount. The user bytes received in the ATP header of the first response packet
- are returned in atpRspUData. ATPXO should be TRUE if you want the request to be part
- of an exactly-once transaction.
-
- Although you don’t provide a BDS, ATPRequest in fact creates one and calls the
- .ATP driver (as in an ATPSndRequest call). For this reason, the abRecord fields
- atpRspBDSPtr and atpNumBufs are used by ATPRequest; you should not expect these
- fields to remain unaltered during or after the function’s execution.
-
- For ATPRequest to receive and correctly deliver the response as a single message, the
- responding end must, upon receiving the request (with an ATPGetRequest call), generate
- the complete response as a message in a single buffer and then call ATPResponse.
-
- Note: The responding end could also use ATPSndRsp and ATPAddRsp provided
- that each response packet (except the last one) contains exactly 578
- ATP data bytes; the last packet in the response can contain less than
- 578 ATP data bytes. Also, if this method is used, only the ATP user
- bytes of the first response packet will be delivered to the requester;
- any information in the user bytes of the remaining response packets
- will not be delivered.
-
- ATPRequest completes when either the transaction is completed or the retry count is
- exceeded.
-
- Result codes noErr No error
- reqFailed Retry count exceeded
- tooManyReqs Too many concurrent requests
- sktClosed Socket closed by a cancel call
- noDataArea Too many outstanding ATP calls
-
- FUNCTION ATPReqCancel (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- Given the handle to the ABusRecord of a previously made ATPSndRequest or ATPRequest
- call, ATPReqCancel dequeues the ATPSndRequest or ATPRequest call, provided that the
- call hasn’t already completed. ATPReqCancel returns noErr if the ATPSndRequest or
- ATPRequest call is successfully removed from the queue. If it returns cbNotFound,
- check the abResult field of abRecord to verify that the ATPSndRequest or ATPRequest
- call has completed and determine its outcome.
-
- Result codes noErr No error
- cbNotFound ATP control block not found
-
- FUNCTION ATPGetRequest (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tATPGetRequest}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> atpSocket {listening socket number}
- <-- atpAddress {source socket address}
- --> atpReqCount {buffer size in bytes}
- --> atpDataPtr {pointer to buffer}
- <-- atpBitMap {transaction bit map}
- <-- atpTransID {transaction ID}
- <-- atpActCount {number of bytes actually received}
- <-- atpUserData {user bytes}
- <-- atpXO {exactly-once flag}
-
- ATPGetRequest sets up the mechanism to receive a request sent by either an ATPSndRequest
- or an ATPRequest call. ATPSocket contains the socket number of the socket that should
- listen for a request; this socket must already have been opened by calling ATPOpenSocket.
- The address of the socket from which the request was sent is returned in atpAddress.
- ATPDataPtr specifies a buffer to store the incoming request; atpReqCount indicates
- the size of the buffer in bytes. The number of bytes actually received in the request
- is returned in atpActCount. ATPUserData contains the user bytes from the ATP header.
- The transaction bit map is returned in atpBitMap. The transaction ID is returned in
- atpTransID. ATPXO will be TRUE if the request is part of an exactly-once transaction.
-
- ATPGetRequest completes when a request is received. To cancel an asynchronous ATPGetRequest
- call, you must call ATPCloseSocket, but this cancels all pending calls involving that
- socket.
-
- Result codes noErr No error
- badATPSkt Bad responding socket
- sktClosed Socket closed by a cancel call
-
- FUNCTION ATPSndRsp (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tATPSdRsp}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> atpSocket {responding socket number}
- --> atpAddress {destination socket address}
- --> atpRspBDSPtr {pointer to response BDS}
- --> atpTransID {transaction ID}
- --> atpEOM {end-of-message flag}
- --> atpNumBufs {number of response packets being sent}
- --> atpBDSSize {number of elements in response BDS}
-
- ATPSndRsp sends a response to another socket. ATPSocket contains the socket number
- from which the response should be sent and atpAddress contains the internet address
- of the socket to which the response should be sent. ATPTransID must contain the
- transaction ID. ATPEOM is TRUE if the response BDS contains the final packet in a
- transaction composed of a group of packets and the number of packets in the response
- is less than expected. ATPRspBDSPtr points to the buffer data structure containing
- the responses to be sent. ATPBDSSize indicates the number of elements in the response
- BDS, and must be in the range 1 to 8. ATPNumBufs indicates the number of response
- packets being sent with this call, and must be in the range 0 to 8.
-
- Note: In some situations, you may want to send only part (or possibly none)
- of your response message back immediately. For instance, you might be
- requested to send back seven disk blocks, but have only enough internal
- memory to store one block. In this case, set atpBDSSize to 7 (total
- number of response packets), atpNumBufs to 0 (number of response
- packets currently being sent), and call ATPSndRsp. Then as you read
- in one block at a time, call ATPAddRsp until all seven response
- datagrams have been sent.
-
- During exactly-once transactions, ATPSndRsp won’t complete until the release packet
- is received or the release timer expires.
-
- Result codes noErr No error
- badATPSkt Bad responding socket
- noRelErr No release received
- sktClosed Socket closed by a cancel call
- noDataArea Too many outstanding ATP calls
- badBuffNum Bad sequence number
-
- FUNCTION ATPAddRsp (abRecord: ABRecHandle) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tATPAddRsp}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> atpSocket {responding socket number}
- --> atpAddress {destination socket address}
- --> atpReqCount {buffer size in bytes}
- --> atpDataPtr {pointer to buffer}
- --> atpTransID {transaction ID}
- --> atpUserData {user bytes}
- --> atpEOM {end-of-message flag}
- --> atpNumRsp {sequence number}
-
- ATPAddRsp sends one additional response packet to a socket that has already been sent
- the initial part of a response via ATPSndRsp. ATPSocket contains the socket number
- from which the response should be sent and atpAddress contains the internet address
- of the socket to which the response should be sent. ATPTransID must contain the
- transaction ID. ATPDataPtr and atpReqCount specify the location and size of a buffer
- that contains the information to send; atpNumRsp is the sequence number of the response.
- ATPEOM is TRUE if this response datagram is the final packet in a transaction composed
- of a group of packets. ATPUserData contains the user bytes to be sent in this response
- datagram’s ATP header.
-
- Note: No BDS is needed with ATPAddRsp because all pertinent information
- is passed within the record.
-
- Result codes noErr No error
- badATPSkt Bad responding socket
- badBuffNum Bad sequence number
- noSendResp ATPAddRsp issued before ATPSndRsp
- noDataArea Too many outstanding ATP calls
-
- FUNCTION ATPResponse (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tATPResponse}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> atpSocket {responding socket number}
- --> atpAddress {destination socket address}
- --> atpTransID {transaction ID)
- --> atpRspUData {user bytes sent in transaction response}
- --> atpRspBuf {pointer to response message buffer}
- --> atpRspSize {size of response message buffer}
-
- ATPResponse is functionally analogous to ATPSndRsp. It sends a response to another
- socket, but doesn’t require the caller to provide a BDS. ATPAddress must contain the
- complete network address of the socket to which the response should be sent (taken
- from the data provided by an ATPGetRequest call). ATPTransID must contain the transaction
- ID. ATPSocket indicates the socket from which the response should be sent (the socket
- on which the corresponding ATPGetRequest was issued). ATPRspBuf points to the buffer
- containing the response message; the size of this buffer must be passed in atpRspSize.
- The four user bytes to be sent in the ATP header of the first response packet are
- passed in atpRspUData. The last packet of the transaction response is sent with the
- EOM flag set.
-
- Although you don’t provide a BDS, ATPResponse in fact creates one and calls the .ATP
- driver (as in an ATPSndRsp call). For this reason, the abRecord fields atpRspBDSPtr
- and atpNumBufs are used by ATPResponse; you should not expect these fields to remain
- unaltered during or after the function’s execution.
-
- During exactly-once transactions ATPResponse won’t complete until the release packet
- is received or the release timer expires.
-
- Warning: The maximum permissible size of the response message is 4624 bytes.
-
- Result codes noErr No error
- badATPSkt Bad responding socket
- noRelErr No release received
- atpLenErr Response too big
- sktClosed Socket closed by a cancel call
- noDataArea Too many outstanding ATP calls
-
- FUNCTION ATPRspCancel (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- Given the handle to the ABusRecord of a previously made ATPSndRsp or ATPResponse
- call, ATPRspCancel dequeues the ATPSndRsp or ATPResponse call, provided that the call
- hasn’t already completed. ATPRspCancel returns noErr if the ATPSndRsp or ATPResponse
- call is successfully removed from the queue. If it returns cbNotFound, check the
- abResult field of abRecord to verify that the ATPSndRsp or ATPResponse call has
- completed and determine its outcome.
-
- Result codes noErr No error
- cbNotFound ATP control block not found
-
- »Example
-
- This example shows the requesting side of an ATP transaction that asks for a 512-byte
- disk block from the responding end. The block number of the file is a byte and is
- contained in myBuffer[0].
-
- VAR
- myABRecord: ABRecHandle;
- myBDSPtr: BDSPtr;
- myBuffer: PACKED ARRAY [0..511] OF CHAR;
- errCode: INTEGER;
- async: BOOLEAN;
-
- BEGIN
- errCode := ATPLoad;
- IF errCode <> noErr THEN
- WRITELN('Error in opening AppleTalk')
- {Maybe serial port B isn't available for use by AppleTalk}
- ELSE
- BEGIN
- {Prepare the BDS; allocate space for a one-element BDS}
- myBDSPtr := BDSPtr(NewPtr(SIZEOF(BDSElement)));
- WITH myBDSPtr^[0] DO
- BEGIN
- buffSize := 512; {size of our buffer used in reception}
- buffPtr := @myBuffer; {pointer to the buffer}
- END;
- {Prepare the ABusRecord}
- myBuffer[0] := CHR(1); {requesting disk block number 1}
- myABRecord := ABRecHandle(NewHandle(atpSize));
- WITH myABRecord^^ DO
- BEGIN
- atpAddress.aNet := 0;
- atpAddress.aNode := 30; {we probably got this from an NBP call}
- atpAddress.aSocket := 15; {socket to send request to}
- atpReqCount := 1; {size of request data field (disk block #)}
- atpDataPtr := @myBuffer; {ptr to request to be sent}
- atpRspBDSPtr := @myBDSPtr;
- atpUserData := 0; {for your use}
- atpXO := FALSE; {at-least-once service}
- atpTimeOut := 5; {5-second timeout}
- atpRetries := 3; {3 retries; request will be sent 4 times max}
- atpNumBufs := 1; {we're only expecting 1 block to be returned}
- END;
- async := FALSE;
- {Send the request and wait for the response}
- errCode := ATPSndRequest(myABRecord, async);
- IF errCode <> noErr THEN
- WRITELN('An error occurred in the ATPSndRequest call')
- ELSE
- BEGIN
- {The disk block requested is now in myBuffer. We can verify }
- { that atpNumRsp contains 1, meaning one response received.}
- . . .
- END;
- END;
- END.
-
- _______________________________________________________________________________
-
- »Name-Binding Protocol
-
- »Data Structures
-
- NBP calls use the following fields:
-
- nbpProto:
- (nbpEntityPtr: EntityPtr; {pointer to entity name}
- nbpBufPtr: Ptr; {pointer to buffer}
- nbpBufSize: INTEGER; {buffer size in bytes}
- nbpDataField: INTEGER; {number of addresses or socket number}
- nbpAddress: AddrBlock; {socket address}
- nbpRetransmitInfo: RetransType); {retransmission information}
-
- When data is sent via NBP, nbpBufSize indicates the size of the data in bytes and
- nbpBufPtr points to a buffer containing the data. When data is received via NBP,
- nbpBufPtr points to a buffer in which the incoming data can be stored and nbpBufSize
- indicates the size of the buffer in bytes. NBPAddress is used in some calls to give
- the internet address of a named entity. The AddrBlock data type is described above
- under “Datagram Delivery Protocol”.
-
- NBPEntityPtr points to a variable of type EntityName, which has the following data
- structure:
-
- TYPE EntityName = RECORD
- objStr: Str32; {object}
- typeStr: Str32; {type}
- zoneStr: Str32 {zone}
- END;
-
- EntityPtr = ^EntityName;
- Str32 = STRING[32];
-
- NBPRetransmitInfo contains information about the number of times a packet should be
- transmitted and the interval between retransmissions:
-
- TYPE RetransType = PACKED RECORD
- retransInterval: Byte; {retransmit interval in }
- { 8-tick units}
- retransCount: Byte {total number of attempts}
- END;
-
- RetransCount contains the total number of times a packet should be transmitted,
- including the first transmission. If retransCount is 0, the packet will be transmitted
- a total of 255 times.
-
- »Using NBP
-
- On a Macintosh 128K, the AppleTalk Manager’s NBP code is read into the application
- heap when any one of the NBP (Pascal) routines is called; you can call the NBPLoad
- function yourself if you want to load the NBP code explicitly. When you’re finished
- with the NBP code and want to reclaim the space it occupies, call NBPUnload. On a
- Macintosh 512K or XL, the NBP code is read in when the .MPP driver is loaded.
-
- Note: When another application starts up, the application heap is
- reinitialized; on a Macintosh 128K, this means that the NBP
- code is lost (and must be reloaded by the next application).
-
- When an entity wants to communicate via an AppleTalk network, it should call NBPRegister
- to place its name and internet address in the names table. When an entity no longer
- wants to communicate on the network, or is being shut down, it should call NBPRemove
- to remove its entry from the names table.
-
- To determine the address of an entity you know only by name, call NBPLookup, which
- returns a list of all entities with the name you specify. Call NBPExtract to extract
- entity names from the list.
-
- If you already know the address of an entity, and want only to confirm that it still
- exists, call NBPConfirm. NBPConfirm is more efficient than NBPLookup in terms of
- network traffic.
-
- »NBP Routines
-
- FUNCTION NBPRegister (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tNBPRegister}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> nbpEntityPtr {pointer to entity name}
- --> nbpBufPtr {pointer to buffer}
- --> nbpBufSize {buffer size in bytes}
- --> nbpAddress.aSocket {socket address}
- --> nbpRetransmitInfo {retransmission information}
-
- NBPRegister adds the name and address of an entity to the node’s names table. NBPEntityPtr
- points to a variable of type EntityName containing the entity’s name. If the name is
- already registered, NBPRegister returns the result code nbpDuplicate. NBPAddress
- indicates the socket for which the name should be registered. NBPBufPtr and nbpBufSize
- specify the location and size of a buffer for NBP to use internally.
-
- While the variable of type EntityName is declared as three 32-byte strings, only the
- actual characters of the name are placed in the buffer pointed to by nbpBufPtr. For
- this reason, nbpBufSize needs only to be equal to the actual length of the name, plus
- an additional 12 bytes for use by NBP.
-
- Warning: This buffer must not be altered or released until the name is
- removed from the names table via an NBPRemove call. If you
- allocate the buffer through a NewHandle call, you must lock
- it as long as the name is registered.
-
- Warning: The zone field of the entity name must be set to the
- meta-character “*”.
-
- Result codes noErr No error
- nbpDuplicate Duplicate name already exists
-
- FUNCTION NBPLookup (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tNBPLookup}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> nbpEntityPtr {pointer to entity name}
- --> nbpBufPtr {pointer to buffer}
- --> nbpBufSize {buffer size in bytes}
- <-> nbpDataField {number of addresses received}
- --> nbpRetransmitInfo {retransmission information}
-
- NBPLookup returns the addresses of all entities with a specified name. NBPEntityPtr
- points to a variable of type EntityName containing the name of the entity whose
- address should be returned. (Meta-characters are allowed in the entity name.) NBPBufPtr
- and nbpBufSize contain the location and size of an area of memory in which the entity
- names and their corresponding addresses should be returned. NBPDataField indicates
- the maximum number of matching names to find addresses for; the actual number of
- addresses found is returned in nbpDataField. NBPRetransmitInfo contains the retry
- interval and the retry count.
-
- When specifying nbpBufSize, for each NBP tuple expected, allow space for the actual
- characters of the name, the address, and four bytes for use by NBP.
-
- Result codes noErr No error
- nbpBuffOvr Buffer overflow
-
- FUNCTION NBPExtract (theBuffer: Ptr; numInBuf: INTEGER; whichOne: INTEGER;
- VAR abEntity: EntityName;
- VAR address: AddrBlock) : OSErr; [Not in ROM]
-
- NBPExtract returns one address from the list of addresses returned by NBPLookup.
- TheBuffer and numInBuf indicate the location and number of tuples in the buffer.
- WhichOne specifies which one of the tuples in the buffer should be returned in the
- abEntity and address parameters.
-
- Result codes noErr No error
- extractErr Can’t find tuple in buffer
-
- FUNCTION NBPConfirm (abRecord: ABRecHandle;
- async: BOOLEAN) : OSErr; [Not in ROM]
-
- ABusRecord
- <-- abOpcode {always tNBPConfirm}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> nbpEntityPtr {pointer to entity name}
- <-- nbpDataField {socket number}
- --> nbpAddress {socket address}
- --> nbpRetransmitInfo {retransmission information}
-
- NBPConfirm confirms that an entity known by name and address still exists (is still
- entered in the names directory). NBPEntityPtr points to a variable of type EntityName
- that contains the name to confirm, and nbpAddress specifies the address to be confirmed.
- (No meta-characters are allowed in the entity name.) NBPRetransmitInfo contains the
- retry interval and the retry count. The socket number of the entity is returned in
- nbpDataField. NBPConfirm is more efficient than NBPLookup in terms of network traffic.
-
- Result codes noErr No error
- nbpConfDiff Name confirmed for different socket
- nbpNoConfirm Name not confirmed
-
- FUNCTION NBPRemove (abEntity: EntityPtr) : OSErr; [Not in ROM]
-
- NBPRemove removes an entity name from the names table of the given entity’s node.
-
- Result codes noErr No error
- nbpNotFound Name not found
-
- FUNCTION NBPLoad : OSErr; [Not in ROM]
-
- On a Macintosh 128K, NBPLoad reads the NBP code from the system resource file into
- the application heap. On a Macintosh 512K or XL, NBPLoad has no effect since the NBP
- code should have already been loaded when the .MPP driver was opened. Normally you’ll
- never need to call NBPLoad, because the AppleTalk Manager calls it when necessary.
-
- Result codes noErr No error
-
- FUNCTION NBPUnload : OSErr; [Not in ROM]
-
- On a Macintosh 128K, NBPUnload makes the NBP code purgeable; the space isn’t actually
- released by the Memory Manager until necessary. On a Macintosh 512K or Macintosh XL,
- NBPUnload has no effect.
-
- Result codes noErr No error
-
- »Example
-
- This example of NBP registers our node as a print spooler, searches for any print
- spoolers registered on the network, and then extracts the information for the first
- one found.
-
- CONST
- mySocket = 20;
-
- VAR
- myABRecord: ABRecHandle;
- myEntity: EntityName;
- entityAddr: AddrBlock;
- nbpNamePtr: Ptr;
- myBuffer: PACKED ARRAY [0..999] OF CHAR;
- errCode: INTEGER;
- async: BOOLEAN;
-
- BEGIN
- errCode := MPPOpen;
- IF errCode <> noErr THEN
- WRITELN('Error in opening AppleTalk')
- {Maybe serial port B isn't available for use by AppleTalk}
- ELSE
- BEGIN
- {Call Memory Manager to allocate ABusRecord}
- myABRecord := ABRecHandle(NewHandle(nbpSize));
- {Set up our entity name to register}
- WITH myEntity DO
- BEGIN
- objStr := 'Gene Station'; {we are called 'Gene Station' }
- typeStr := 'PrintSpooler'; { and are of type 'PrintSpooler'}
- zoneStr := '*';
- {Allocate data space for the entity name (used by NBP)}
- nbpNamePtr := NewPtr(LENGTH(objStr) + LENGTH(typeStr) +
- LENGTH(zoneStr) + 12);
- END;
- {Set up the ABusRecord for the NBPRegister call}
- WITH myABRecord^^ DO
- BEGIN
- nbpEntityPtr := @myEntity;
- nbpBufPtr := nbpNamePtr; {buffer used by NBP internally}
- nbpBufSize := nbpNameBufSize;
- nbpAddress.aSocket := mySocket; {socket to register us on}
- nbpRetransmitInfo.retransInterval := 8; {retransmit every 64 }
- nbpRetransmitInfo.retransCount := 3; { ticks and try 3 times}
- END;
- async := FALSE;
- errCode := NBPRegister(myABRecord, async);
- IF errCode <> noErr THEN
- WRITELN('Error occurred in the NBPRegister call')
- {Maybe the name is already registered somewhere else on the }
- { network.}
- ELSE
- BEGIN
- {Now that we've registered our name, find others of type }
- { 'PrintSpooler'.}
- WITH myEntity DO
- BEGIN
- objStr := '='; {any one of type }
- typeStr := 'PrintSpooler'; { “PrintSpooler” }
- zoneStr := '*'; { in our zone}
- END;
- WITH myABRecord^^ DO
- BEGIN
- nbpEntityPtr := @myEntity;
- nbpBufPtr := @myBuffer; {buffer to place responses in}
- nbpBufSize := SIZEOF(myBuffer);
- {The field nbpDataField, before the NBPLookup call, represents an }
- { approximate number of responses. After the call, nbpDataField }
- { contains the actual number of responses received.}
- nbpDataField := 100; {we want about 100 responses back}
- END;
- errCode := NBPLookup(myABRecord, async); {make sync call}
- IF errCode <> noErr THEN
- WRITELN('An error occurred in the NBPLookup')
- {Did the buffer overflow?}
- ELSE
- BEGIN
- {Get the first reply}
- errCode := NBPExtract(@mybuffer, myABRecord^^.nbpDataField, 1,
- myEntity, entityAddr);
- {The socket address and name of the entity are returned here. If we }
- { want all of them, we'll have to loop for each one in the buffer.}
- IF errCode <> noErr THEN WRITELN('Error in NBPExtract');
- {Maybe the one we wanted wasn't in the buffer}
- END;
- END;
- END;
- END.
-
- _______________________________________________________________________________
-
- »Miscellaneous Routines
-
- FUNCTION GetNodeAddress (VAR myNode,myNet: INTEGER) : OSErr; [Not in ROM]
-
- GetNodeAddress returns the current node ID and network number of the caller. If the
- .MPP driver isn’t installed, it returns noMPPErr. If myNet contains 0, this means
- that a bridge hasn’t yet been found.
-
- Result codes noErr No error
- noMPPErr MPP driver not installed
-
- FUNCTION IsMPPOpen : BOOLEAN; [Not in ROM]
-
- IsMPPOpen returns TRUE if the .MPP driver is loaded and running.
-
- FUNCTION IsATPOpen : BOOLEAN; [Not in ROM]
-
- IsATPOpen returns TRUE if the .ATP driver is loaded and running.
-
- _______________________________________________________________________________
-
-
- æKY New…AppleTalk…Manager…Pascal…Interface
- æC »NEW APPLETALK MANAGER PASCAL INTERFACE AppleTalkManager
- _______________________________________________________________________________
-
- In addition to the interface documented in the previous section, a new parameter
- block–style interface to the AppleTalk Manager is now available for Pascal programmers.
- This new interface, referred to as the preferred interface, is available in addition
- to the Pascal interface described in the previous section, which is referred to as
- the alternate interface. All AppleTalk Manager calls, old and new, are supported by
- the preferred interface.
-
- The alternate interface has not been extended to support the new AppleTalk Manager
- calls. However, the alternate interface provides the only implementation of LAPRead
- and DDPRead. These are higher-level calls not directly supported through the assembly-language
- interface. Developers will wish to use the alternate interface for these calls, and
- also for compatibility with previous applications. In all other cases, it is recommended
- that the new preferred interface be used.
-
- _______________________________________________________________________________
-
- »Using Pascal
-
- All AppleTalk Manager calls in the preferred interface are essentially equivalent to
- the corresponding assembly-language calls. Their form is
-
- FUNCTION MPPCall (pbPtr: Ptr; asyncFlag: BOOLEAN) : OSErr;
-
- where pbPtr points to a device manager parameter block, and asyncFlag is TRUE if the
- call is to be executed asynchronously. Three parameter block types are provided by
- the preferred interface (MPP, ATP, and XPP). The MPP parameter block is shown below.
- The ATP parameter block is shown in the following section, and the XPP parameter
- block is shown in the “Calling the .XPP Driver” section of this document. The field
- names in these parameter blocks are the same as the parameter block offset names
- defined in the assembly-language section (except as documented below). The caller
- fills in the parameter block with the fields as specified in that section and issues
- the appropriate call. The interface issues the actual device manager control call.
-
- On asynchronous calls, the caller may pass a completion routine pointer in the parameter
- block, at offset ioCompletion. This routine will be executed upon completion of the
- call. It is executed at interrupt level and must not make any memory manager calls.
- If it uses application globals, it must ensure that register A5 is set up correctly;
- for details see SetupA5 and RestoreA5 in the Operating System Utilities chapter. If
- no completion routine is desired, ioCompletion should be set to NIL.
-
- Asynchronous calls return control to the caller with result code of noErr as soon as
- they are queued to the driver. This isn’t an indication of successful completion.
- To determine when the call is actually completed, if you don’t want to use a completion
- routine, you can poll the ioResult field; this field is set to 1 when the call is
- made, and receives the actual result code upon completion.
-
- Refer to the appropriate sections of this chapter for the parameter blocks used by
- each MPP and ATP call. As different MPP and ATP calls take different arguments in
- their parameter block, two Pascal variant records have been defined to account for
- all the different cases. These parameter blocks are shown in the sections that
- follow. The first four fields (which are the same for all calls) are automatically
- filled in by the device manager. The csCode and ioRefnum fields are automatically
- filled in by the interface, depending on which call is being made, except in XPP
- where the caller must fill in the ioRefnum. The ioVRefnum field is unused.
-
- There are two fields that at the assembly-language level have more than one name.
- These two fields have been given only one name in the preferred interface. These are
- entityPtr and ntqelPtr, which are both referred to as entityPtr, and atpSocket and
- currBitmap, which are both referred to as atpSocket. These are the only exceptions to
- the naming convention.
-
- »MPP Parameter Block
-
- MPPParamBlock = PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: INTEGER; {queue type}
- ioTrap: INTEGER; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OSErr; {result code}
- ioNamePtr: StringPtr; {command result (ATP user bytes) [long]}
- ioVRefNum: INTEGER; {volume reference or drive number}
- ioRefNum: INTEGER; {driver reference number}
- csCode: INTEGER; {call command code AUTOMATICALLY SET}
-
- CASE MPPParmType OF
- LAPWriteParm:
- (filler0:INTEGER;
- wdsPointer:Ptr); {->Write Data Structure}
- AttachPHParm,DetachPHParm:
- (protType:Byte; {ALAP Protocol Type}
- filler1:Byte;
- handler:Ptr); {->protocol handler routine}
- OpenSktParm,CloseSktParm,WriteDDPParm:
- (socket:Byte; {socket number}
- checksumFlag:Byte; {checksum flag}
- listener:Ptr); {->socket listener routine}
- RegisterNameParm,LookupNameParm,ConfirmNameParm,RemoveNameParm:
- (interval:Byte; {retry interval}
- count:Byte; {retry count}
- entityPtr:Ptr; {->names table element or }
- { ->entity name}
- CASE MPPParmType OF
- RegisterNameParm:
- (verifyFlag:Byte; {set if verify needed}
- filler3:Byte);
- LookupNameParm:
- (retBuffPtr:Ptr; {->return buffer}
- retBuffSize:INTEGER; {return buffer size}
- maxToGet:INTEGER; {matches to get}
- numGotten:INTEGER); {matched gotten}
- ConfirmNameParm:
- (confirmAddr:AddrBlock; {->entity}
- newSocket:Byte; {socket number}
- filler4:Byte));
-
- SetSelfSendParm:
- (newSelfFlag:Byte; {self-send toggle flag}
- oldSelfFlag:Byte); {previous self-send state}
- KillNBPParm:
- (nKillQEl:Ptr); {ptr to Q element to cancel}
- END;
-
- »ATP Parameter Block
-
- ATPParamBlock = PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: INTEGER; {queue type}
- ioTrap: INTEGER; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OSErr; {result code}
- userData: LONGINT; {ATP user bytes [long]}
- reqTID: INTEGER; {request transaction ID}
- ioRefNum: INTEGER; {driver reference number
- csCode: INTEGER; {Call command code }
- { AUTOMATICALLY SET}
- atpSocket: Byte; {currBitMap or socket number}
- atpFlags: Byte; {control information}
- addrBlock: AddrBlock; {source/dest. socket address}
- reqLength: INTEGER; {request/response length}
- reqPointer: Ptr; {-> request/response data}
- bdsPointer: Ptr; {-> response BDS}
- CASE MPPParmType OF
- SendRequestParm,NSendRequestParm:
- (numOfBuffs:Byte; {numOfBuffs}
- timeOutVal:Byte; {timeout interval}
- numOfResps:Byte; {number responses actually received}
- retryCount:Byte; {number of retries}
- intBuff:INTEGER); {used internally for NSendRequest}
- SendResponseParm:
- (filler0:Byte; {number of responses being sent}
- bdsSize:Byte; {number of BDS elements}
- transID:INTEGER); {transaction ID}
- GetRequestParm:
- (bitMap:Byte; {bit map}
- filler1:Byte);
- AddResponseParm:
- (rspNum:Byte; {sequence number}
- filler2:Byte);
- KillSendReqParm,KillGetReqParm:
- (aKillQEl:Ptr); {ptr to Q element to cancel}
- END;
-
- The following table is a complete list of all the parameter block calls provided by
- the preferred interface.
-
- AppleTalk
- Manager
- Routine Preferred Interface Call
-
- AttachPH Function PAttachPH (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- DetachPH Function PDetachPH (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- WriteLAP Function PWriteLAP (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- OpenSkt Function POpenSkt (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- CloseSkt Function PCloseSkt (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- WriteDDP Function PWriteDDP (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- RegisterName Function PRegisterName (thePBptr: MPPPBPtr;
- async: BOOLEAN) : OSErr;
- LookupName Function PLookupName (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- ConfirmName Function PConfirmName (thePBptr: MPPPBPtr;
- async: BOOLEAN) : OSErr;
- RemoveName Function PRemoveName (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- OpenATPSkt Function POpenATPSkt (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- CloseATPSkt Function PCloseATPSkt (thePBptr: ATPPBPtr;
- async: BOOLEAN) : OSErr;
- SendRequest Function PSendRequest (thePBptr: ATPPBPtr;
- async: BOOLEAN) : OSErr;
- GetRequest Function PGetRequest (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- SendResponse Function PSendResponse (thePBptr: ATPPBPtr;
- async: BOOLEAN) : OSErr;
- AddResponse Function PAddResponse(thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- ReltCB Function PRelTCB (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- RelRspCB Function PRelRspCB (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- SetSelfSend Function PSetSelfSend (thePBptr: MPPPBPtr;
- async: BOOLEAN) : OSErr;
- NSendRequest Function PNSendRequest (thePBptr: ATPPBPtr;
- async: BOOLEAN) : OSErr;
- KillSendReq Function PKillSendReq (thePBptr: ATPPBPtr;
- async: BOOLEAN) : OSErr;
- KillGetReq Function PKillGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- KillNBP Function PKillNBP (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
-
- _______________________________________________________________________________
-
- »Building Data Structures
-
- Because it is difficult for Pascal to deal with certain assembly-language structures,
- the preferred interface provides a number of routines for building these structures.
- These routines are summarized below.
-
- PROCEDURE BuildLAPwds (wdsPtr,dataPtr: Ptr;
- destHost,protoType,frameLen: INTEGER);
-
- This routine builds a single-frame write data structure LAP WDS for use with the
- PWriteLAP call. Given a buffer of length frameLen pointed to by dataPtr, it fills in
- the WDS pointed to by wdsPtr and sets the destination node and protocol type as
- indicated by destHost and protoType, respectively. The WDS indicated must contain at
- least two elements.
-
- PROCEDURE BuildDDPwds (wdsPtr,headerPtr,dataPtr: Ptr; destAddress: AddrBlock;
- DDPType : INTEGER; dataLen: INTEGER);
-
- This routine builds a single-frame write data structure DDP WDS, for use with the
- PWriteDDP call. Given a header buffer of at least 17 bytes pointed to by headerPtr
- and a data buffer of length dataLen pointed to by dataPtr, it fills in the WDS pointed
- to by wdsPtr, and sets the destination address and protocol type as indicated by
- destaddress and DDPtype, respectively. The WDS indicated must contain at least 3
- elements.
-
- PROCEDURE NBPSetEntity (buffer: Ptr; nbpObject,nbpType,nbpZone: Str32);
-
- This routine builds an NBP entity structure, for use with the PLookupNBP and PConfirmName
- calls. Given a buffer of at least the size of the EntityName data structure (99
- bytes) pointed to by buffer, this routine sets the indicated object, type, and zone
- in that buffer.
-
- PROCEDURE NBPSetNTE (ntePtr: Ptr; nbpObject,nbpType,nbpZone: Str32;
- Socket: INTEGER);
-
- This routine builds an NBP names table entry, for use with the PRegisterName call.
- Given a names table entry of at least the size of the EntityName data structure plus
- nine bytes (108 bytes) pointed to by ntePtr, this routine sets the indicated object,
- type, zone, and socket in that names table entry.
-
- FUNCTION NBPExtract (theBuffer: Ptr; numInBuf: INTEGER; whichOne: INTEGER; VAR abEntity:
- EntityName; VAR address: AddrBlock) : OSErr;
-
- This routine is provided in the alternate interface, but can be used as provided for
- extracting NBP entity names from a look-up response buffer.
-
- FUNCTION GetBridgeAddress: INTEGER;
-
- This routine returns the current address of a bridge in the low byte, or zero if
- there is none.
-
- FUNCTION BuildBDS (buffPtr,bdsPtr: Ptr; buffSize: INTEGER) : INTEGER;
-
- This routine builds a BDS, for use with the ATP calls. Given a data buffer of length
- buffSize pointed to by buffPtr, it fills in the BDS pointed to by bdsPtr. The buffer
- will be broken up into pieces of maximum size (578 bytes). The user bytes in the BDS
- are not modified by this routine. This routine is provided only as a convenience;
- generally the caller will be able to build the BDS completely from Pascal without
- it.
-
- _______________________________________________________________________________
-
-
- æKY Picking…a…Node…Address…in…the…Server…Range
- æC »PICKING A NODE ADDRESS IN THE SERVER RANGE AppleTalkManager
- _______________________________________________________________________________
-
- Normally upon opening, the node number picked by the AppleTalk manager will be in the
- node number range ($01–$7F). It is possible to indicate that a node number in the
- server range ($80–$FE) is desired. Picking a number in the server range is a more
- time-consuming but more thorough process, and it’s required for server nodes because
- it greatly decreases the possibility of a node number conflict.
-
- To open AppleTalk with a server node number, an extended open call is used. An
- extended open call is indicated by having the immediate bit set in the Open trap
- itself. In the extended open call, the high bit (bit 31) of the extension longword
- field (ioMix) indicates whether a server or workstation node number should be picked.
- Set this bit to 1 to request a server node number. The rest of this field should be
- zero, as should all other unused fields in the queue element. A server node number
- can only be requested on the first Open call to the .MPP driver.
-
- _______________________________________________________________________________
-
-
- æKY Sending…Packets…to…One’s…Own…Node
- æC »SENDING PACKETS TO ONE’S OWN NODE AppleTalkManager
- _______________________________________________________________________________
-
- Upon opening, the ability to send a packet to one’s own node (intranode delivery) is
- disabled. This feature of the AppleTalk Manager can be manipulated through the
- SetSelfSend function. Once enabled, it is possible, at all levels, to send packets
- to entities within one’s own node. An example of where this might be desirable is an
- application sending data to a print spooler that is actually running in the background
- on the same node.
-
- Enabling (or disabling) this feature affects the entire node and should be performed
- with care. For instance, a desk accessory may not expect to receive names from
- within its own node as a response to an NBP look-up; enabling this feature from an
- application could break the desk accessory. All future programs should be written
- with this feature in mind.
-
- FUNCTION PSetSelfSend (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter Block
- --> 26 csCode word Always PSetSelfSend
- --> 28 newSelfFlag byte New SelfSend flag
- <-- 29 oldSelfFlag byte Old SelfSend flag
-
- PSetSelfSend enables or disables the intranode delivery feature of the AppleTalk
- Manager. If newSelfFlag is nonzero, the feature will be enabled; otherwise it will
- be disabled. The previous value of the flag will be returned in oldSelfFlag.
-
- Result Codes noErr No error
-
- _______________________________________________________________________________
-
-
- æKY ATP…Driver…Changes
- æC »ATP DRIVER CHANGES AppleTalkManager
- _______________________________________________________________________________
-
- Changes to the ATP driver include the ability to send an ATP request through a specific
- socket rather than having ATP open a new socket, a new call to abort outstanding
- SendRequest calls, and a new call to abort specific outstanding GetRequest calls.
-
- _______________________________________________________________________________
-
- »Sending an ATP Request Through a Specified Socket
-
- ATP requests can now be sent through client-specified sockets. ATP previously would
- open a dynamic socket, send the request through it, and close the socket when the
- request was completed. The client can now choose to send a request through an already-opened
- socket; this also allows more than one request to be sent per socket. A new call,
- PNSendRequest, has been added for this purpose. The function of the old SendRequest
- call itself remains unchanged.
-
- FUNCTION PNSendRequest (thePBptr: ATPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 18 userData longword User bytes
- <-- 22 reqTID word Transaction ID used in request
- --> 26 csCode word Always sendRequest
- <-> 28 atpSocket byte Socket to send request on
- or current bitmap
- <-> 29 atpFlags byte Control information
- --> 30 addrBlock longword Destination socket address
- --> 34 reqLength word Request size in bytes
- --> 36 reqPointer pointer Pointer to request data
- --> 40 bdsPointer pointer Pointer to response BDS
- --> 44 numOfBuffs byte Number of responses expected
- --> 45 timeOutVal byte Timeout interval
- <-- 46 numOf Resps byte Number of responses received
- <-> 47 retryCount byte Number of retries
- <-- 48 intBuff word Used internally
-
- The PNSendRequest call is functionally equivalent to the SendRequest call, however
- PNSendRequest allows you to specify, in the atpSocket field, the socket through which
- the request is to be sent. This socket must have been previously opened through an
- OpenATPSkt request (otherwise a badATPSkt error will be returned). Note that PNSendRequest
- requires two additional bytes of memory at the end of the parameter block, immediately
- following the retryCount. These bytes are for the internal use of the AppleTalk
- Manager and should not be modified while the PNSendRequest call is active.
-
- There is a machine-dependent limit as to the number of concurrent PNSendRequests that
- can be active on a given socket. If this limit is exceeded, the error tooManyReqs is
- returned.
-
- One additional difference between SendRequest and PNSendRequest is that a PNSendRequest
- can only be aborted by a PKillSendReq call (see below), whereas a SendRequest can be
- aborted by either a RelTCB or KillSendReq call.
-
- Result Codes noErr No error
- reqFailed Retry count exceeded
- tooManyReqs Too many concurrent requests
- noDataArea Too many outstanding ATP calls
- reqAborted Request cancelled by user
-
- _______________________________________________________________________________
-
- »Aborting ATP SendRequests
-
- The RelTCB call is still supported, but only for aborting SendRequests. To abort
- PNSendRequests, a new call, PKillSendReq, has been added. This call will abort both
- SendRequests and PNSendRequests. PKillSendReq’s only argument is the queue element
- pointer of the request to be aborted. The queue element pointer is passed at the
- offset of the PKillSendReq queue element specified by aKillQE1.
-
- FUNCTION PKillSendReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 26 csCode word Always PKillSendReq
- --> 44 aKillQEl pointer Pointer to queue element
-
- PKillSendReq is functionally equivalent to RelTCB, except that it takes different
- arguments and will abort both SendRequests and PNSendRequests. To abort one of these
- calls, place a pointer to the queue element of the call to abort in aKillQEl and
- issue the PKillSendReq call.
-
- Result Codes noErr No error
- cbNotFound aKillQEl does not point to a SendReq
- or NSendReq queue element
-
- _______________________________________________________________________________
-
- »Aborting ATP GetRequests
-
- ATP GetRequests can now be aborted through the PKillGetReq call. This call looks and
- works just like the PKillSendReq call, and is used to abort a specific GetRequest
- call. Previously it was necessary to close the socket to abort all GetRequest calls
- on the socket.
-
- FUNCTION PKillGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 26 csCode word Always PKillGetReq
- --> 44 aKillQEl pointer Pointer to queue element
-
- PKillGetReq will abort a specific outstanding GetRequest call (as opposed to closing
- the socket, which aborts all outstanding GetRequests on that socket). The call will
- be completed with a reqAborted error. To abort a GetRequest, place a pointer to the
- queue element of the call to abort in aKillQEl and issue the PKillGetReq call.
-
- Result Codes noErr No error
- cbNotFound aKillQEl does not point to a GetReq
- queue element
-
- _______________________________________________________________________________
-
-
- æKY Name…Binding…Protocol…Changes
- æC »NAME BINDING PROTOCOL CHANGES AppleTalkManager
- _______________________________________________________________________________
-
- Changes to the Name Binding Protocol include supporting multiple concurrent requests
- and a means for aborting an active request.
-
- »Multiple Concurrent NBP Requests
-
- NBP now supports multiple concurrent active requests. Specifically, a number of
- LookupNames, RegisterNames and ConfirmNames can all be active concurrently. The
- maximum number of concurrent requests is machine dependent; if it is exceeded the
- error tooManyReqs will be returned. Active requests can be aborted by the PKillNBP
- call.
-
- »KillNBP function
-
- FUNCTION PKillNBP (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
-
- •••Refer to Technical Note #199:•••
-
- Parameter block
- --> 26 csCode word Always PKillNBP
- --> 28 aKillQEl pointer Pointer to queue element
-
- PKillNBP is used to abort an outstanding LookupName, RegisterName or ConfirmName
- request. To abort one of these calls, place a pointer to the queue element of the
- call to abort in a KillQEl and issue the PKillNBP call. The call will be completed
- with a ReqAborted error.
-
- Result Codes noErr No error
- cbNotFound aKillQEl does not point to a valid
- NBP queue element
-
- _______________________________________________________________________________
-
-
- æKY Variable…Resources
- æC »VARIABLE RESOURCES AppleTalkManager
- _______________________________________________________________________________
-
- The table below lists machine-dependent resources for the different Macintosh system
- configurations. The RAM-based resources are available through the AppleShare Server.
-
- Resource Macintosh Plus RAM-Based Macintosh SE Macintosh II
-
- Protocol
- Handlers 4 8 8 8
-
- Statically
- Assigned
- Sockets 14* 12 12 14
-
- Concurrent
- ATP SendRequests 6 12 12 12
-
- ATP Sockets 6 32 32 126
-
- Concurrent
- ATP Responses 8 16 16 32
-
- Concurrent
- NBP Requests 1 6 6 10
-
- Concurrent
- ASP Sessions N/A 5 10 20
-
- Concurrent
- ATP NSendRequests
- Per Socket ** N/A 9 14 62
-
- * Includes dynamic sockets
- ** Determined dynamically at runtime based on CPU speed.
- N/A : Not Applicable
-
- _______________________________________________________________________________
-
-
- æKY Calling…the…AppleTalk…Manager…from…Assembly…Language
- æC »CALLING THE APPLETALK MANAGER FROM ASSEMBLY LANGUAGE AppleTalkManager
- _______________________________________________________________________________
-
- This section discusses how to use the AppleTalk Manager from assembly language.
- Equivalent Pascal information is given in the preceding section.
-
- All routines make Device Manager Control calls. The description of each routine
- includes a list of the fields needed. Some of these fields are part of the parameter
- block described in the Device Manager chapter; additional fields are provided for the
- AppleTalk Manager.
-
- The number next to each field name indicates the byte offset of the field from the
- start of the parameter block pointed to by A0. An arrow next to each parameter name
- indicates whether it’s an input, output, or input/output parameter:
-
- Arrow Meaning
- --> Parameter is passed to the routine
- <-- Parameter is returned by the routine
- <-> Parameter is passed to and returned by the routine
-
- All Device Manager Control calls return an integer result code of type OSErr in the
- ioResult field. Each routine description lists all of the applicable result codes
- generated by the AppleTalk Manager, along with a short description of what the result
- code means. Lengthier explanations of all the result codes can be found in the summary
- at the end of this chapter. Result codes from other parts of the Operating System may
- also be returned. (See Appendix A for a list of all result codes.)
-
- _______________________________________________________________________________
-
- »Opening AppleTalk
-
- •••Refer to Technical Note #224:•••
-
- Two tests are made at system startup to determine whether the .MPP driver should be
- opened at that time. If port B is already in use, or isn’t configured for AppleTalk,
- .MPP isn’t opened until explicitly requested by an application; otherwise it’s opened
- at system startup.
-
- It’s the application’s responsibility to test the availability of port B before
- opening AppleTalk. Assembly-language programmers can use the Pascal calls MPPOpen and
- ATPLoad to open the .MPP and .ATP drivers.
-
- The global variable SPConfig is used for configuring the serial ports; it’s copied
- from a byte in parameter RAM (which is discussed in the Operating System Utilities
- chapter). The low-order four bits of this variable contain the current configuration
- of port B. The following use types are provided as global constants for testing or
- setting the configuration of port B:
-
- useFree .EQU 0 ;unconfigured
- useATalk .EQU 1 ;configured for AppleTalk
- useAsync .EQU 2 ;configured for the Serial Driver
-
- The application shouldn’t attempt to open AppleTalk unless SPConfig is equal to
- either useFree or useATalk.
-
- A second test involves the global variable PortBUse; the low-order four bits of this
- byte are used to monitor the current use of port B. If PortBUse is negative, the
- program is free to open AppleTalk. If PortBUse is positive, the program should test
- to see whether port B is already being used by AppleTalk; if it is, the low-order
- four bits of PortBUse will be equal to the use type useATalk.
-
- The .MPP driver sets PortBUse to the correct value (useATalk) when it’s opened and
- resets it to $FF when it’s closed. Bits 4-6 of this byte are used for driver-specific
- information; ATP uses bit 4 to indicate whether it’s currently opened:
-
- atpLoadedBit .EQU 4 ;set if ATP is opened
-
- »Example
-
- The following code illustrates the use of the SPConfig and PortBUse variables.
-
- MOVE #-<atpUnitNum+1>,atpRefNum(A0) ;save known ATP refNum in
- ; case ATP not opened
- OpenAbus SUB #ioQElSize,SP ;allocate queue entry
- MOVE.L SP,A0 ;A0 -> queue entry
- CLR.B ioPermssn(A0) ;make sure permission's clear
- MOVE.B PortBUse,D1 ;is port B in use?
- BPL.S @10 ;if so, make sure by AppleTalk
- MOVEQ #portNotCf,D0 ;assume port not configured for AppleTalk
- MOVE.B SPConfig,D1 ;get configuration data
- AND.B #$0F,D1 ;mask it to low 4 bits
- SUBQ.B #useATalk,D1 ;unconfigured or configured for AppleTalk
- BGT.S @30 ;if not, return error
- LEA mppName,A1 ;A1 = address of driver name
- MOVE.L A1,ioFileName(A0) ;set in queue entry
- _Open ;open MPP
- BNE.S @30 ;return error, if it can't load it
- BRA.S @20 ;otherwise, go check ATP
- @10 MOVEQ #portInUse,D0 ;assume port in use error
- AND.B #$0F,D1 ;clear all but use bits
- SUBQ.B #useATalk,D1 ;is AppleTalk using it?
- BNE.S @30 ;if not, then error
- @20 MOVEQ #0,D0 ;assume no error
- BTST #atpLoadedBit,PortBUse ;ATP already open?
- BNE.S @30 ;just return if so
- LEA atpName,A1 ;A1 = address of driver name
- MOVE.L A1,ioFileName(A0) ;set in queue entry
- _Open ;open ATP
- @30 ADD #ioQElSize,SP ;deallocate queue entry
- RTS ;and return
- mppName .BYTE 4 ;length of .MPP driver name
- .ASCII '.MPP' ;name of .MPP driver
- atpName .BYTE 4 ;length of .ATP driver name
- .ASCII '.ATP' ;name of .ATP driver
-
- _______________________________________________________________________________
-
- »AppleTalk Link Access Protocol
-
- »Data Structures
-
- An ALAP frame is composed of a three-byte header, up to 600 bytes of data, and a
- two-byte frame check sequence (Figure 6). You can use the following global constants
- to access the contents of an ALAP header:
-
- lapDstAdr .EQU 0 ;destination node ID
- lapSrcAdr .EQU 1 ;source node ID
- lapType .EQU 2 ;ALAP protocol type
- lapHdSz .EQU 3 ;ALAP header size
-
- •••Refer to Figure 6.•••
-
- Figure 6–ALAP Frame
-
- Two of the protocol handlers in every node are used by DDP. These protocol handlers
- service frames with ALAP protocol types equal to the following global constants:
-
- shortDDP .EQU 1 ;short DDP header
- longDDP .EQU 2 ;long DDP header
-
- When you call ALAP to send a frame, you pass it information about the frame in a
- write data structure, which has the format shown in Figure 7.
-
- •••Refer to Figure 7.•••
-
- Figure 7–Write Data Structure for ALAP
-
- If you specify a destination node ID of 255, the frame will be broadcast to all
- nodes. The byte that’s “used internally” is used by the AppleTalk Manager to store
- the address of the node sending the frame.
-
- »Using ALAP
-
- Most programs will never need to call ALAP, because higher-level protocols will
- automatically call ALAP as necessary. If you do want to send a frame directly via an
- ALAP, call the WriteLAP function. There’s no ReadLAP function in assembly language;
- if you want to read ALAP frames, you must call AttachPH to add your protocol handler
- to the node’s protocol handler table. The ALAP module will examine every incoming
- frame and call your protocol handler for each frame received with the correct ALAP
- protocol. When your program no longer wants to receive frames with a particular ALAP
- protocol type value, it can call DetachPH to remove the corresponding protocol handler
- from the protocol handler table.
-
- See the “Protocol Handlers and Socket Listeners” section for information on how to
- write a protocol handler.
-
- »ALAP Routines
-
- WriteLAP function
-
- Parameter block
- --> 26 csCode word ;always writeLAP
- --> 30 wdsPointer pointer ;write data structure
-
- WriteLAP sends a frame to another node. The frame data and destination of the frame
- are described by the write data structure pointed to by wdsPointer. The first two
- data bytes of an ALAP frame sent to another computer using the AppleTalk Manager must
- indicate the length of the frame in bytes. The ALAP protocol type byte must be in the
- range 1 to 127.
-
- Result codes noErr No error
- excessCollsns No CTS received after 32 RTS’s
- ddpLengthErr Packet length exceeds maximum
- lapProtErr Invalid ALAP protocol type
-
- AttachPH function
-
- Parameter block
- --> 26 csCode word ;always attachPH
- --> 28 protType byte ;ALAP protocol type
- --> 30 handler pointer ;protocol handler
-
- AttachPH adds the protocol handler pointed to by handler to the node’s protocol
- table. ProtType specifies what kind of frame the protocol handler can service. After
- AttachPH is called, the protocol handler is called for each incoming frame whose ALAP
- protocol type equals protType.
-
- Result codes noErr No error
- lapProtErr Error attaching protocol type
-
- DetachPH function
-
- Parameter block
- --> 26 csCode word ;always detachPH
- --> 28 protType byte ;ALAP protocol type
-
- DetachPH removes from the node’s protocol table the specified ALAP protocol type and
- corresponding protocol handler.
-
- Result codes noErr No error
- lapProtErr Error detaching protocol type
-
- _______________________________________________________________________________
-
- »Datagram Delivery Protocol
-
- »Data Structures
-
- A DDP datagram consists of a header followed by up to 586 bytes of actual data
- (Figure 8). The headers can be of two different lengths; they’re identified by the
- following ALAP protocol types:
-
- shortDDP .EQU 1 ;short DDP header
- longDDP .EQU 2 ;long DDP header
-
- •••Refer to Figure 8.•••
-
- Figure 8–DDP Datagram
-
- Long DDP headers (13 bytes) are used for sending datagrams between two or more different
- AppleTalk networks. You can use the following global constants to access the contents
- of a long DDP header:
-
- ddpHopCnt .EQU 0 ;count of bridges passed (4 bits)
- ddpLength .EQU 0 ;datagram length (10 bits)
- ddpChecksum .EQU 2 ;checksum
- ddpDstNet .EQU 4 ;destination network number
- ddpSrcNet .EQU 6 ;source network number
- ddpDstNode .EQU 8 ;destination node ID
- ddpSrcNode .EQU 9 ;source node ID
- ddpDstSkt .EQU 10 ;destination socket number
- ddpSrcSkt .EQU 11 ;source socket number
- ddpType .EQU 12 ;DDP protocol type
-
- The size of a DDP long header is given by the following constant:
-
- ddpHSzLong .EQU ddpType+1
-
- The short headers (five bytes) are used for datagrams sent to sockets within the same
- network as the source socket. You can use the following global constants to access
- the contents of a short DDP header:
-
- ddpLength .EQU 0 ;datagram length
- sDDPDstSkt .EQU ddpChecksum ;destination socket number
- sDDPSrcSkt .EQU sDDPDstSkt+1 ;source socket number
- sDDPType .EQU sDDPSrcSkt+1 ;DDP protocol type
-
- The size of a DDP short header is given by the following constant:
-
- ddpHSzShort .EQU sDDPType+1
-
- The datagram length is a ten-bit field. You can use the following global constant as
- a mask for these bits:
-
- ddpLenMask .EQU $03FF
-
- The following constant indicates the maximum length of a DDP datagram:
-
- ddpMaxData .EQU 586
-
- When you call DDP to send a datagram, you pass it information about the datagram in a
- write data structure with the format shown in Figure 9.
-
- •••Refer to Figure 9.•••
-
- Figure 9–Write Data Structure for DDP
-
- The first seven bytes are used internally for the ALAP header and the DDP datagram
- length and checksum. The other bytes used internally store the network number, node
- ID, and socket number of the socket client sending the datagram.
-
- Warning: The first entry in a DDP write data structure must begin at
- an odd address.
-
- If you specify a node ID of 255, the datagram will be broadcast to all nodes within
- the destination network. A network number of 0 means the local network to which the
- node is connected.
-
- Warning: DDP always destroys the high-order byte of the destination
- network number when it sends a datagram with a short header.
- Therefore, if you want to reuse the first entry of a DDP write
- data structure entry, you must restore the destination network number.
-
- »Using DDP
-
- Before it can use a socket, the program must call OpenSkt, which adds a socket and
- its socket listener to the socket table. When a client is finished using a socket,
- call CloseSkt, which removes the socket’s entry from the socket table. To send a
- datagram via DDP, call WriteDDP. If you want to read DDP datagrams, you must write
- your own socket listener. DDP will send every incoming datagram for that socket to
- your socket listener.
-
- See the “Protocol Handlers and Socket Listeners” section for information on how to
- write a socket listener.
-
- »DDP Routines
-
- OpenSkt function
-
- Parameter block
- --> 26 csCode word ;always openSkt
- <-> 28 socket byte ;socket number
- --> 30 listener pointer ;socket listener
-
- OpenSkt adds a socket and its socket listener to the socket table. If the socket
- parameter is nonzero, it must be in the range 64 to 127, and it specifies the socket’s
- number; if socket is 0, OpenSkt opens a socket with a socket number in the range 128
- to 254, and returns it in the socket parameter. Listener contains a pointer to the
- socket listener.
-
- OpenSkt will return ddpSktErr if you pass the number of an already opened socket, if
- you pass a socket number greater than 127, or if the socket table is full (the socket
- table can hold a maximum of 12 sockets).
-
- Result codes noErr No error
- ddpSktErr Socket error
-
- CloseSkt function
-
- Parameter block
- --> 26 csCode word ;always closeSkt
- --> 28 socket byte ;socket number
-
- CloseSkt removes the entry of the specified socket from the socket table. If you pass
- a socket number of 0, or if you attempt to close a socket that isn’t open, CloseSkt
- will return ddpSktErr.
-
- Result codes noErr No error
- ddpSktErr Socket error
-
- WriteDDP function
-
- Parameter block
- --> 26 csCode word ;always writeDDP
- --> 28 socket byte ;socket number
- --> 29 checksumFlag byte ;checksum flag
- --> 30 wdsPointer pointer ;write data structure
-
- WriteDDP sends a datagram to another socket. WDSPointer points to a write data structure
- containing the datagram and the address of the destination socket. If checksumFlag is
- TRUE, WriteDDP will compute the checksum for all datagrams requiring long headers.
-
- Result codes noErr No error
- ddpLenErr Datagram length too big
- ddpSktErr Socket error
- noBridgeErr No bridge found
-
- _______________________________________________________________________________
-
- »AppleTalk Transaction Protocol
-
- »Data Structures
-
- An ATP packet consists of an ALAP header, DDP header, and ATP header, followed by
- actual data (Figure 10). You can use the following global constants to access the
- contents of an ATP header:
-
- atpControl .EQU 0 ;control information
- atpBitMap .EQU 1 ;bit map
- atpRespNo .EQU 1 ;sequence number
- atpTransID .EQU 2 ;transaction ID
- atpUserData .EQU 4 ;user bytes
-
- The size of an ATP header is given by the following constant:
-
- atpHdSz .EQU 8
-
- •••Refer to Figure 10.•••
-
- Figure 10–ATP Packet
-
- ATP packets are identified by the following DDP protocol type:
-
- atp .EQU 3
-
- The control information contains a function code and various control bits. The function
- code identifies either a TReq, TResp, or TRel packet with one of the following global
- constants:
-
- atpReqCode .EQU $40 ;TReq packet
- atpRspCode .EQU $80 ;TResp packet
- atpRelCode .EQU $C0 ;TRel packet
-
- The send-transmission-status, end-of-message, and exactly-once bits in the control
- information are accessed via the following global constants:
-
- atpSTSBit .EQU 3 ;send-transmission-status bit
- atpEOMBit .EQU 4 ;end-of-message bit
- atpXOBit .EQU 5 ;exactly-once bit
-
- Many ATP calls require a field called atpFlags (Figure 11), which contains the above
- three bits plus the following two bits:
-
- sendChk .EQU 0 ;send-checksum bit
- tidValid .EQU 1 ;transaction ID validity bit
-
- •••Refer to Figure 11.•••
-
- Figure 11–ATPFlags Field
-
- The maximum number of response packets in an ATP transaction is given by the following
- global constant:
-
- atpMaxNum .EQU 8
-
- When you call ATP to send responses, you pass the responses in a response BDS, which
- is a list of up to eight elements, each of which contains the following:
-
- bdsBuffSz .EQU 0 ;size of data to send
- bdsBuffAddr .EQU 2 ;pointer to data
- bdsUserData .EQU 8 ;user bytes
-
- When you call ATP to receive responses, you pass it a response BDS with up to eight
- elements, each in the following format:
-
- bdsBuffSz .EQU 0 ;buffer size in bytes
- bdsBuffAddr .EQU 2 ;pointer to buffer
- bdsDataSz .EQU 6 ;number of bytes actually received
- bdsUserData .EQU 8 ;user bytes
-
- The size of a BDS element is given by the following constant:
-
- bdsEntrySz .EQU 12
-
- ATP clients are identified by internet addresses in the form shown in Figure 12.
-
- •••Refer to Figure 12.•••
-
- Figure 12–Internet Address
-
- »Using ATP
-
- Before you can use ATP on a Macintosh 128K, the .ATP driver must be read from the
- system resource file via a Device Manager Open call. The name of the .ATP driver is
- '.ATP' and its reference number is –11. When the .ATP driver is opened, it reads its
- ATP code into the application heap and installs a task into the vertical retrace
- queue.
-
- Warning: When another application starts up, the application heap is
- reinitialized; on a Macintosh 128K, this means that the ATP
- code is lost (and must be reloaded by the next application).
-
- When you’re through using ATP on a Macintosh 128K, call the Device Manager Close
- routine—the system will be returned to the state it was in before the
- .ATP driver was opened.
-
- On a Macintosh 512K or XL, the .ATP driver will have been loaded into the system heap
- either at system startup or upon execution of a Device Manager Open call loading MPP.
- You shouldn’t close the .ATP driver on a Macintosh 512K or XL; AppleTalk expects it
- to remain open on these systems.
-
- To send a request to another socket and get a response, call SendRequest. The call
- terminates when either an entire response is received or a specified retry timeout
- interval elapses. To open a socket for the purpose of responding to requests, call
- OpenATPSkt. Then call GetRequest to receive a request; when a request is received,
- the call is completed. After receiving and servicing a request, call SendResponse to
- return response information. If you cannot or do not want to send the entire response
- all at once, make a SendResponse call to send some of the response, and then call
- AddResponse later to send the remainder of the response. To close a socket opened for
- the purpose of sending responses, call CloseATPSkt.
-
- During exactly-once transactions, SendResponse doesn’t terminate until the transaction
- is completed via a TRel packet, or the retry count is exceeded.
-
- Warning: Don’t modify the parameter block passed to an ATP call until
- the call is completed.
-
- »ATP Routines
-
- OpenATPSkt function
-
- Parameter block
- --> 26 csCode word ;always openATPSkt
- <-> 28 atpSocket byte ;socket number
- --> 30 addrBlock long word ;socket request specification
-
- OpenATPSkt opens a socket for the purpose of receiving requests. ATPSocket contains
- the socket number of the socket to open. If it’s 0, a number is dynamically assigned
- and returned in atpSocket. AddrBlock contains a specification of the socket addresses
- from which requests will be accepted. A 0 in the network number, node ID, or socket
- number field of addrBlock means that requests will be accepted from every network,
- node, or socket, respectively.
-
- Result codes noErr No error
- tooManySkts Too many responding sockets
- noDataArea Too many outstanding ATP calls
-
- CloseATPSkt function
-
- Parameter block
- --> 26 csCode word ;always closeATPSkt
- --> 28 atpSocket byte ;socket number
-
- CloseATPSkt closes the socket whose number is specified by atpSocket, for the purpose
- of receiving requests.
-
- Result codes noErr No error
- noDataArea Too many outstanding ATP calls
-
- SendRequest function
-
- Parameter block
- --> 18 userData long word ;user bytes
- <-- 22 reqTID word ;transaction ID used in request
- --> 26 csCode word ;always sendRequest
- <-- 28 currBitMap byte ;bit map
- <-> 29 atpFlags byte ;control information
- --> 30 addrBlock long word ;destination socket address
- --> 34 reqLength word ;request size in bytes
- --> 36 reqPointer pointer ;pointer to request data
- --> 40 bdsPointer pointer ;pointer to response BDS
- --> 44 numOfBuffs byte ;number of responses expected
- --> 45 timeOutVal byte ;timeout interval
- <-- 46 numOfResps byte ;number of responses received
- <-> 47 retryCount byte ;number of retries
-
- SendRequest sends a request to another socket and waits for a response. UserData
- contains the four user bytes. AddrBlock indicates the socket to which the request
- should be sent. ReqLength and reqPointer contain the size and location of the request
- to send. BDSPointer points to a response BDS where the responses are to be returned;
- numOfBuffs indicates the number of responses requested. The number of responses
- received is returned in numOfResps. If a nonzero value is returned in numOfResps, you
- can examine currBitMap to determine which packets of the transaction were actually
- received and to detect pieces for higher-level recovery, if desired.
-
- TimeOutVal indicates the number of seconds that SendRequest should wait for a response
- before resending the request. RetryCount indicates the maximum number of retries
- SendRequest should attempt. The end-of-message flag of atpFlags will be set if the
- EOM bit is set in the last packet received in a valid response sequence. The exactly-once
- flag should be set if you want the request to be part of an exactly-once transaction.
-
- To cancel a SendRequest call, you need the transaction ID; it’s returned in reqTID.
- You can examine reqTID before the completion of the call, but its contents are valid
- only after the tidValid bit of atpFlags has been set.
-
- SendRequest completes when either an entire response is received or the retry count
- is exceeded.
-
- Note: The value provided in retryCount will be modified during SendRequest
- if any retries are made. This field is used to monitor the number of
- retries; for each retry, it’s decremented by 1.
-
- Result codes noErr No error
- reqFailed Retry count exceeded
- tooManyReqs Too many concurrent requests
- noDataArea Too many outstanding ATP calls
- reqAborted Request canceled by user
-
- GetRequest function
-
- Parameter block
- <-- 18 userData long word ;user bytes
- --> 26 csCode word ;always getRequest
- --> 28 atpSocket byte ;socket number
- <-- 29 atpFlags byte ;control information
- <-- 30 addrBlock long word ;source of request
- <-> 34 reqLength word ;request buffer size
- --> 36 reqPointer pointer ;pointer to request buffer
- <-- 44 bitMap byte ;bit map
- <-- 46 transID word ;transaction ID
-
- GetRequest sets up the mechanism to receive a request sent by a SendRequest call.
- UserData returns the four user bytes from the request. ATPSocket contains the socket
- number of the socket that should listen for a request. The internet address of the
- socket from which the request was sent is returned in addrBlock. ReqLength and reqPointer
- indicate the size (in bytes) and location of a buffer to store the incoming request.
- The actual size of the request is returned in reqLength. The transaction bit map and
- transaction ID will be returned in bitMap and transID. The exactly-once flag in
- atpFlags will be set if the request is part of an exactly-once transaction.
-
- GetRequest completes when a request is received.
-
- Result codes noErr No error
- badATPSkt Bad responding socket
-
- SendResponse function
-
- Parameter block
- <-- 18 userData long word ;user bytes from TRel
- <-- 22 reqTID word ;transaction ID used in request
- --> 26 csCode word ;always sendResponse
- --> 28 atpSocket byte ;socket number
- --> 29 atpFlags byte ;control information
- --> 30 addrBlock long word ;response destination
- --> 40 bdsPointer pointer ;pointer to response BDS
- --> 44 numOfBuffs byte ;number of response packets being sent
- --> 45 bdsSize byte ;BDS size in elements
- --> 46 transID word ;transaction ID
-
- SendResponse sends a response to a socket. If the response was part of an exactly-once
- transaction, userData will contain the user bytes from the TRel packet. ATPSocket
- contains the socket number from which the response should be sent. The end-of-message
- flag in atpFlags should be set if the response contains the final packet in a transaction
- composed of a group of packets and the number of responses is less than requested.
- AddrBlock indicates the address of the socket to which the response should be sent.
- BDSPointer points to a response BDS containing room for the maximum number of responses
- to be sent; bdsSize contains this maximum number. NumOfBuffs contains the number of
- response packets to be sent in this call; you may wish to make AddResponse calls to
- complete the response. TransID indicates the transaction ID of the associated request.
-
- During exactly-once transactions, SendResponse doesn’t complete until either a TRel
- packet is received from the socket that made the request, or the retry count is
- exceeded.
-
- Result codes noErr No error
- badATPSkt Bad responding socket
- noRelErr No release received
- noDataArea Too many outstanding ATP calls
- badBuffNum Sequence number out of range
-
- AddResponse function
-
- Parameter block
- --> 18 userData long word ;user bytes
- --> 26 csCode word ;always addResponse
- --> 28 atpSocket byte ;socket number
- --> 29 atpFlags byte ;control information
- --> 30 addrBlock long word ;response destination
- --> 34 reqLength word ;response size
- --> 36 reqPointer pointer ;pointer to response
- --> 44 rspNum byte ;sequence number
- --> 46 transID word ;transaction ID
-
- AddResponse sends an additional response packet to a socket that has already been
- sent the initial part of a response via SendResponse. UserData contains the four user
- bytes. ATPSocket contains the socket number from which the response should be sent.
- The end-of-message flag in atpFlags should be set if this response packet is the
- final packet in a transaction composed of a group of packets and the number of responses
- is less than requested. AddrBlock indicates the socket to which the response should
- be sent. ReqLength and reqPointer contain the size (in bytes) and location of the
- response to send; rspNum indicates the sequence number of the response (in the range
- 0 to 7). TransID must contain the transaction ID.
-
- Warning: If the transaction is part of an exactly-once transaction, the
- buffer used in the AddResponse call must not be altered or
- released until the corresponding SendResponse call has completed.
-
- Result codes noErr No error
- badATPSkt Bad responding socket
- noSendResp AddResponse issued before SendResponse
- badBuffNum Sequence number out of range
- noDataArea Too many outstanding ATP calls
-
- RelTCB function
-
- Parameter block
- --> 26 csCode word ;always relTCB
- --> 30 addrBlock long word ;destination of request
- --> 46 transID word ;transaction ID of request
-
- RelTCB dequeues the specified SendRequest call and returns the result code reqAborted
- for the aborted call. The transaction ID can be obtained from the reqTID field of the
- SendRequest queue entry; see the description of SendRequest for details.
-
- Result codes noErr No error
- cbNotFound ATP control block not found
- noDataArea Too many outstanding ATP calls
-
- RelRspCB function
-
- Parameter block
- --> 26 csCode word ;always relRspCB
- --> 28 atpSocket byte ;socket number that request was received on
- --> 30 addrBlock long word ;source of request
- --> 46 transID word ;transaction ID of request
-
- In an exactly-once transaction, RelRspCB cancels the specified SendResponse, without
- waiting for the release timer to expire or a TRel packet to be received. No error is
- returned for the SendResponse call. Whan called to cancel a transaction that isn’t
- using exactly-once service, RelRspCB returns cbNotFound. The transaction ID can be
- obtained from the reqTID field of the SendResponse queue entry; see the description
- of SendResponse for details.
-
- Result codes noErr No error
- cbNotFound ATP control block not found
-
- _______________________________________________________________________________
-
- »Name-Binding Protocol
-
- »Data Structures
-
- The first two bytes in the NBP header (Figure 13) indicate the type of the packet,
- the number of tuples in the packet, and an NBP packet identifier. You can use the
- following global constants to access these bytes:
-
- nbpControl .EQU 0 ;packet type
- nbpTCount .EQU 0 ;tuple count
- nbpID .EQU 1 ;packet identifier
- nbpTuple .EQU 2 ;start of first tuple
-
- •••Refer to Figure 13.•••
-
- Figure 13–NBP Packet
-
- NBP packets are identified by the following DDP protocol type:
-
- nbp .EQU 2
-
- NBP uses the following global constants in the nbpControl field to identify NBP
- packets:
-
- brRq .EQU 1 ;broadcast request
- lkUp .EQU 2 ;lookup request
- lkUpReply .EQU 3 ;lookup reply
-
- NBP entities are identified by internet address in the form shown in Figure 14 below.
- Entities are also identified by tuples, which include both an internet address and an
- entity name. You can use the following global constants to access information in
- tuples:
-
- tupleNet .EQU 0 ;network number
- tupleNode .EQU 2 ;node ID
- tupleSkt .EQU 3 ;socket number
- tupleEnum .EQU 4 ;used internally
- tupleName .EQU 5 ;entity name
-
- The meta-characters in an entity name can be identified with the following global
- constants:
-
- equals .EQU '=' ;“wild-card” meta-character
- star .EQU '*' ;“this zone” meta-character
-
- •••Refer to Figure 14.•••
-
- Figure 14–Names Table Entry
-
- The maximum number of tuples in an NBP packet is given by the following global constant:
-
- tupleMax .EQU 15
-
- Entity names are mapped to sockets via the names table. Each entry in the names table
- has the structure shown in Figure 14.
-
- You can use the following global constants to access some of the elements of a names
- table entry:
-
- ntLink .EQU 0 ;pointer to next entry
- ntTuple .EQU 4 ;tuple
- ntSocket .EQU 7 ;socket number
- ntEntity .EQU 9 ;entity name
-
- The socket number of the names information socket is given by the following global
- constant:
-
- nis .EQU 2
-
- »Using NBP
-
- On a Macintosh 128K, before calling any other NBP routines, call the LoadNBP function,
- which reads the NBP code from the system resource file into the application heap.
- (The NBP code is part of the .MPP driver, which has a driver reference number of
- –10.) When you’re finished with NBP and want to reclaim the space its code occupies,
- call UnloadNBP. On a Macintosh 512K or XL, the NBP code is read in when the .MPP
- driver is loaded.
-
- Warning: When an application starts up, the application heap is
- reinitialized; on a Macintosh 128K, this means that the
- NBP code is lost (and must be reloaded by the next application).
-
- When an entity wants to communicate via an AppleTalk network, it should call RegisterName
- to place its name and internet address in the names table. When an entity no longer
- wants to communicate on the network, or is being shut down, it should call RemoveName
- to remove its entry from the names table.
-
- To determine the address of an entity you know only by name, call LookupName, which
- returns a list of all entities with the name you specify. If you already know the
- address of an entity, and want only to confirm that it still exists, call ConfirmName.
- ConfirmName is more efficient than LookupName in terms of network traffic.
-
- »NBP Routines
-
- RegisterName function
-
- Parameter block
- --> 26 csCode word ;always registerName
- --> 28 interval byte ;retry interval
- <-> 29 count byte ;retry count
- --> 30 ntQElPtr pointer ;names table element pointer
- --> 34 verifyFlag byte ;set if verify needed
-
- RegisterName adds the name and address of an entity to the node’s names table. NTQElPtr
- points to a names table entry containing the entity’s name and internet address (in
- the form shown in Figure 14 above). Meta-characters aren’t allowed in the object and
- type fields of the entity name; the zone field, however, must contain the meta-character
- “*”. If verifyFlag is TRUE, RegisterName checks on the network to see if the name is
- already in use, and returns a result code of nbpDuplicate if so. Interval and count
- contain the retry interval in eight-tick units and the retry count. When a retry is
- made, the count field is modified.
-
- •••Refer to Technical Note #225:•••
-
- Warning: The names table entry passed to RegisterName remains the
- property of NBP until removed from the names table. Don’t
- attempt to remove or modify it. If you’ve allocated memory
- using a NewHandle call, you must lock it as long as the name
- is registered.
-
- Warning: VerifyFlag should normally be set before calling RegisterName.
-
- Result codes noErr No error
- nbpDuplicate Duplicate name already exists
- nbpNISErr Error opening names information socket
-
- LookupName function
-
- Parameter block
- --> 26 csCode word ;always lookupName
- --> 28 interval byte ;retry interval
- <-> 29 count byte ;retry count
- --> 30 entityPtr pointer ;pointer to entity name
- --> 34 retBuffPtr pointer ;pointer to buffer
- --> 38 retBuffSize word ;buffer size in bytes
- --> 40 maxToGet word ;matches to get
- <-- 42 numGotten word ;matches found
-
- LookupName returns the addresses of all entities with a specified name. EntityPtr
- points to the entity’s name (in the form shown in Figure 14 above). Meta-characters
- are allowed in the entity name. RetBuffPtr and retBuffSize contain the location and
- size of an area of memory in which the tuples describing the entity names and their
- corresponding addresses should be returned. MaxToGet indicates the maximum number of
- matching names to find addresses for; the actual number of addresses found is returned
- in numGotten. Interval and count contain the retry interval and the retry count.
- LookupName completes when either the number of matches is equal to or greater than
- maxToGet, or the retry count has been exceeded. The count field is decremented for
- each retransmission.
-
- Note: NumGotten is first set to 0 and then incremented with each match
- found. You can test the value in this field, and can start examining
- the received addresses in the buffer while the lookup continues.
-
- Result codes noErr No error
- nbpBuffOvr Buffer overflow
-
- ConfirmName function
-
- Parameter block
- --> 26 csCode word ;always confirmName
- --> 28 interval byte ;retry interval
- <-> 29 count byte ;retry count
- --> 30 entityPtr pointer ;pointer to entity name
- --> 34 confirmAddr pointer ;entity address
- <-- 38 newSocket byte ;socket number
-
- ConfirmName confirms that an entity known by name and address still exists (is still
- entered in the names directory). EntityPtr points to the entity’s name
- (in the form shown in Figure 14 above). ConfirmAddr specifies the address to confirmed.
- No meta-characters are allowed in the entity name. Interval and count contain the
- retry interval and the retry count. The socket number of the entity is returned in
- newSocket. ConfirmName is more efficient than LookupName in terms of network traffic.
-
- Result codes noErr No error
- nbpConfDiff Name confirmed for different socket
- nbpNoConfirm Name not confirmed
-
- RemoveName function
-
- Parameter block
- --> 26 csCode word ;always removeName
- --> 30 entityPtr pointer ;pointer to entity name
-
- RemoveName removes an entity name from the names table of the given entity’s node.
-
- Result codes noErr No error
- nbpNotFound Name not found
-
- LoadNBP function
-
- Parameter block
- --> 26 csCode word ;always loadNBP
-
- On a Macintosh 128K, LoadNBP reads the NBP code from the system resource file into
- the application heap; on a Macintosh 512K or XL it has no effect.
-
- Result codes noErr No error
-
- UnloadNBP function
-
- Parameter block
- --> 26 csCode word ;always unloadNBP
-
- On a Macintosh 128K, UnloadNBP makes the NBP code purgeable; the space isn’t actually
- released by the Memory Manager until necessary. On a Macintosh 512K or XL, UnloadNBP
- has no effect.
-
- Result codes noErr No error
-
- _______________________________________________________________________________
-
-
- æKY Extended…Protocol…Package…Driver
- æC »EXTENDED PROTOCOL PACKAGE DRIVER AppleTalkManager
- _______________________________________________________________________________
-
- The Extended Protocol Package (XPP) driver is intended to implement several AppleTalk
- communication protocols in the same package for ease of use. The
- .XPP driver currently consists of two modules that operate on two levels: the low-level
- module implements the workstation side of AppleTalk Session Protocol, and the high-level
- module implements a small portion of the workstation side of the AppleTalk Filing
- Protocol.
-
- This driver adds functionality to the AppleTalk manager by providing services additional
- to those provided in the .MPP and .ATP drivers. Figure 2 shows the Macintosh AppleTalk
- drivers and the protocols accessible through each driver.
-
- The .XPP driver maps an AFP call from the client workstation into one or more ASP
- calls. .XPP provides one client-level call for AFP.
-
- The implementation of AFP in the .XPP driver is very limited. Most calls are a very
- simple one-to-one mapping from an AFP call to an ASP command without any interpretation
- of the syntax of the AFP command by the .XPP driver. Refer to the “Mapping AFP
- Commands” section of this chapter for further information.
-
- _______________________________________________________________________________
-
- »Version
-
- The .XPP driver supports ASP Version (hex) $100, as described in Inside AppleTalk.
-
- _______________________________________________________________________________
-
- »Error Reporting
-
- Errors are returned by the .XPP driver in the ioResult field of the Device Manager
- Control calls.
-
- The error conditions reported by the .XPP driver may represent the unsuccessful
- completion of a routine in more than just one process involved in the interaction of
- the session. System-level, .XPP driver, AppleTalk, and server errors can all turn
- up in the ioResult field.
-
- AFP calls return codes indicating the unsuccessful completion of AFP commands in the
- Command Result field of the parameter block (described below).
-
- An application using the .XPP driver should respond appropriately to error conditions
- reported from the different parts of the interaction. As shown in Figure 3, the
- following errors can be returned in the ioResult field:
-
- 1. System-level errors
-
- System errors returned by the .XPP driver indicate such conditions
- as the driver not being open or a specific system call not being
- supported. For a complete list of result codes returned by the
- Macintosh system software, refer to Appendix A.
-
- 2. XPP errors (for example, “Session not opened”)
-
- The .XPP driver can also return errors resulting from its own
- activity (for example, the referenced session isn’t open). The
- possible .XPP driver errors returned are listed in the .XPP driver
- results codes section with each function that can return the code.
-
- 3. AppleTalk Errors (returned from lower-level protocols)
-
- .XPP may also return errors from lower-level protocols (for example,
- “Socket not open”). Possible error conditions and codes are described
- elsewhere in this chapter.
-
- 4. An ASP-specific error could be returned from an ASP server in
- response to a failed OpenSession call. Errors of this type, returned
- by the server to the workstation, are documented both in Inside
- AppleTalk, section 11, “AppleTalk Session Protocol”, and in the .XPP
- driver results code section of this chapter.
-
- 5. The AppleTalk Filing Protocol defines errors that are returned from
- the server to the workstation client. These errors are returned in
- the cmdResult field of the parameter block (error type 5 in Figure 15).
- This field is valid if no system-level error is returned by the call.
- Note that at the ASP level, the cmdResult field is client-defined data
- and may not be an error code.
-
- •••Refer to Figure 15.•••
-
- Figure 15–Error Reporting
-
- _______________________________________________________________________________
-
- ».XPP Driver Functions Overview
-
- The paragraphs below describe the implementation of ASP in the .XPP driver. For more
- detailed information about ASP, refer to Inside AppleTalk, Section 11, “AppleTalk
- Session Protocol (ASP)”.
-
- »Using AppleTalk Name Binding Protocol
-
- A server wishing to advertise its service on the AppleTalk network calls ATP to open
- an ATP responding socket known as the session listening socket (SLS). The server
- then calls the Name Binding Protocol (NBP) to register a name on this socket. At
- this point, the server calls the server side of ASP to pass it the address of the
- SLS. Then, the server starts listening on the SLS for session opening requests
- coming over the network.
-
- »Opening and Closing Sessions
-
- When a workstation wishes to access a server, the workstation must call NBP to discover
- the SLS for that server. Then the workstation calls ASP to open a session with that
- server.
-
- After determining the SLS (address) of the server, the workstation client issues an
- OpenSession (or AFPLogin) call to open a session with that server. As a result of
- this call, ASP sends a special OpenSession packet (an ATP request) to the SLS; this
- packet carries the address of a workstation socket for use in the session. This
- socket is referred to as the workstation session socket (WSS). If the server is
- unable to set up the session, it returns an error. If the request is successful, the
- server returns no error, and the session is opened. The open session packet also
- contains a version number so that both ends can verify that they are speaking the
- same version of ASP.
-
- The AbortOS function can be used to abort an outstanding OpenSession request before
- it has completed.
-
- The workstation client closes the session by issuing a CloseSession (or AFPLogout).
- The CloseSession call aborts any calls that are active on the session and closes the
- session. The session can also be closed by the server or by ASP itself, such as when
- one end of the session fails. The CloseAll call (which should be used with care)
- aborts every session that the driver has active.
-
- »Session Maintenance
-
- A session will remain open until it is explicitly terminated by the ASP client at
- either end or until one of the sessions ends, fails, or becomes unreachable.
-
- »Commands on an Open Session
-
- Once a session has been opened, the workstation client can send a sequence of commands
- over the session to the server end. The commands are delivered in the same order as
- they are issued at the workstation end, and replies to the commands are returned to
- the workstation end.
-
- Three types of commands can be made on an open session. These commands are UserCommand,
- UserWrite, and AFPCall functions described in the following paragraphs.
-
- UserCommand calls are similar to ATP requests. The workstation client sends a command
- (included in a variable size command block) to the server client requesting it to
- perform a particular function and send back a variable size command reply. Examples
- of such commands vary from a request to open a particular file on a file server, to
- reading a certain range of bytes from a device. In the first case, a small amount of
- reply data is returned; in the second case a multiple-packet reply might be generated.
-
- The .XPP driver does not interpret the command block or in any way participate in
- executing the command’s function. It simply conveys the command block, included in a
- higher-level format, to the server end of the session, and returns the command reply
- to the workstation-end client. The command reply consists of a four-byte command
- result and a variable size command reply block.
-
- UserWrite allows the workstation to convey blocks of data to the server. UserWrite
- is used to transfer a variable size block of data to the server end of the session
- and to receive a reply.
-
- The AFPCall function provides a mechanism for passing an AFP command to the server
- end of an open session and receiving a reply. The first byte of the AFPCall command
- buffer contains the code for the AFP command that is to be passed to the server for
- execution. Most AFP calls are implemented through a very simple one-to-one mapping
- that takes the call and makes an ASP command out of it.
-
- The AFPCall function can have one of four different, but very similar, formats.
-
- »Getting Server Status Information
-
- ASP provides a service to allow its workstation clients to obtain a block of service
- status information from a server without the need for opening a session. The GetStatus
- function returns a status block from the server identified by the indicated address.
- ASP does not impose any structure on the status block. This structure is defined by
- the protocol above ASP.
-
- »Attention Mechanism
-
- Attentions are defined in ASP as a way for the server to alert the workstation of
- some event or critical piece of information. The ASP OpenSession and AFPLogin calls
- include a pointer to an attention routine in their parameter blocks. This attention
- routine is called by the .XPP driver when it receives an attention from the server
- and also when the session is closing as described below.
-
- In addition, upon receiving an OpenSession call or AFPLogin call, the .XPP driver
- sets the first two bytes of the session control block (SCB) to zero. When the .XPP
- driver receives an attention, the first two bytes of the SCB are set to the attention
- bytes from the packet (which are always nonzero).
-
- Note: A higher-level language such as Pascal may not wish to have a low-level
- attention routine called. A Pascal program can poll the attention bytes,
- and if they are ever nonzero, the program will know that an attention
- has come in. (It would then set the attention bytes back to zero.)
- Of course, two or more attentions could be received between successive
- polls, and only the last one would be recorded.
-
- The .XPP driver also calls the attention routine when the session is closed by either
- the server, workstation, or ASP itself (if the ASP session times out). In these
- cases, the attention bytes in the SCB are unchanged.
-
- »The Attention Routine
-
- The attention routine is called at interrupt level and must observe interrupt conventions.
- Specifically, the interrupt routine can change registers A0 through A3 and D0 through
- D3 and it must not make any Memory Manager calls.
-
- It will be called with
-
- • D0 (word) equal to the SessRefnum for that session (see OpenSession
- Function)
- • D1 (word) equal to the attention bytes passed by the server (or zero
- if the session is closing)
-
- Return with an RTS (return from subroutine) to resume normal execution.
-
- The next section describes the calls that can be made to the .XPP driver.
-
- _______________________________________________________________________________
-
-
- æKY Calling…the….XPP…Driver
- æC »CALLING THE .XPP DRIVER AppleTalkManager
- _______________________________________________________________________________
-
- This section describes how to use the .XPP driver and how to call the .XPP driver
- routines from assembly language and Pascal.
-
- _______________________________________________________________________________
-
- »Using XPP
-
- The .XPP driver implements the workstation side of ASP and provides a mechanism for
- the workstation to send AppleTalk Filing Protocol (AFP) commands to the server.
-
- »Allocating Memory
-
- Every call to the .XPP driver requires the caller to pass in whatever memory is
- needed by the driver for the call, generally at the end of the queue element. When a
- session is opened, the memory required for maintenance of that session
- (that is, the Session Control Block) is also passed in.
-
- For standard Device Manager calls, a queue element of a specific size equal to IOQElSize
- is allocated. When issuing many calls to XPP, it is the caller’s responsibility to
- allocate a queue element that is large enough to accommodate the .XPP driver’s requirements
- for executing that call, as defined below. Once allocated, that memory can’t be
- modified until the call completes.
-
- »Opening the .XPP Driver
-
- To open the .XPP driver, issue a Device Manager Open call. (Refer to the Device
- Manager chapter.) The name of the .XPP driver is '.XPP'. The original Macintosh
- ROMs require that .XPP be opened only once. With new ROMs, the .XPP unit number can
- always be obtained through an Open call. With old ROMs only, the .XPP unit number
- must be hard coded to XPPUnitNum (40) since only one Open call can be issued to the
- driver.
-
- The .XPP driver cannot be opened unless AppleTalk is open. The application must
- ensure that the .MPP and .ATP drivers are opened, as described earlier in this chapter.
-
- The xppLoaded bit (bit 5) in the PortBUse byte in low memory indicates whether or not
- the .XPP driver is open.
-
- »Example
-
- The following is an example of the procedure an application might use to open the
- .XPP driver.
-
- ; Routine: OpenXPP
- ;
- ; Open the .XPP driver and return the driver refNum for it.
- ;
- ; Exit: D0 = error code (ccr's set)
- ; D1 = XPP driver refNum (if no errors)
- ;
- ; All other registers preserved
- ;
- xppUnitNum EQU 40 ;default XPP driver number
- xppTfRNum EQU -(xppUnitNum+1) ;default XPP driver refNum
-
- OpenXPP
- MOVE.L A0-A1/D2,-(SP) ;save registers
- MOVE ROM85,D0 ;check ROM type byte
- BPL.S @10 ;branch if >=128K ROMs
- BTST #xppLoadedBit,PortBUse ;is the XPP driver open already?
- BEQ.S @10 ;if not open, then branch to Open code
- MOVE #xppTfRNum,D1 ;else use this as driver refnum
- MOVEQ #0,D0 ;set noErr
- BRA.S @90 ;and exit
- ;
- ; XPP driver not open. Make an _Open call to it. If using a 128K
- ; ROM machine and the driver is already open, we will make another
- ; Open call to it just so we get the correct driver refNum.
- ;
- @10 SUB #ioQElSize,SP ;allocate temporary param block
- MOVE.L SP,A0 ;A0 -> param block
- LEA XPPName, A1 ;A1 -> XPP (ASP/AFP) driver name
- MOVE.L A1,ioFileName(A0) ;driver name into param block
- CLR.B ioPermssn(A0) ;clear permissions byte
- _Open
- MOVE ioRefNum(A0),D1 ;D1=driver refNum (invalid if error)
- ADD #ioQElSize,SP ;deallocate temp param block
- @90 MOVE.L (SP)+,A0-A1/D2 ;restore registers
- TST D0 ;error? (set ccr's)
- RTS
-
- XPPName DC.B 4 ;length of string
- DC.B '.XPP' ;driver name
-
- From Pascal, XPP can be opened through the OpenXPP call, which returns the driver’s
- reference number:
-
- FUNCTION OpenXPP (VAR xppRefnum: INTEGER) : OSErr;
-
- »Open Errors
-
- Errors returned when calling the Device Manager Open routine if the function does not
- execute properly include the following:
-
- • errors returned by System
- • portInUse is returned if the AppleTalk port is in use by a driver
- other than AppleTalk or if AppleTalk is not open.
-
- »Closing the .XPP Driver
-
- To close the .XPP driver, call the Device Manager Close routine.
-
- Warning: There is generally no reason to close the driver. Use this
- call sparingly, if at all. This call should generally be used
- only by system-level applications.
-
- »Close Errors
-
- Errors returned when calling the Device Manager Close routine if the function does
- not execute properly include the following:
-
- • errors returned by System
- • closeErr (new ROMs only) is returned if you try to close the driver
- and there are sessions active through that driver. When sessions are
- active, closeErr is returned and the driver remains open.
- • on old ROMs the driver is closed whether or not sessions are active
- and no error is returned. Results are unpredictable if sessions are
- still active.
-
- »Session Control Block
-
- The session control block (SCB) is a nonrelocatable block of data passed by the
- caller to XPP upon session opening. XPP reserves this block for use in maintaining an
- open session. The SCB size is defined by the constant scbMemSize. The SCB is a
- locked block, and as long as the session is open, the SCB cannot be modified in any
- way by the application. There is one SCB for each open session. This block can be
- reused once a CloseSess call is issued and completed for that session or when the
- session is indicated as closed.
-
- _______________________________________________________________________________
-
- »How to Access the .XPP Driver
-
- This section contains information for programmers using Pascal and assembly-language
- routines.
-
- All .XPP driver routines can be executed either synchronously (meaning that the
- application can’t continue until the routine is completed) or asynchronously
- (meaning that the application is free to perform other tasks while the routine is
- executing).
-
- XPP calls are made from Pascal in the same manner as MPP and ATP calls, with the
- exception that when making XPP calls the caller must set the XPP driver’s refnum.
- This refnum is returned in the XPPOpen call’s parameter block.
-
- A Pascal variant record has been defined for all XPP calls. This parameter block is
- detailed in the “.XPP Driver Parameter Block Record” section below. The first four
- fields (which are the same for all calls) are automatically filled in by the device
- manager. The csCode field is automatically filled in by Pascal, depending on which
- call is being made. The caller must, however, set the ioRefnum field to XPP’s reference
- number, as returned in the OpenXPP call. The ioVRefnum field is unused.
-
- Note that the parameter block is defined so as to be the maximum size used by any
- call. Different calls take different size parameter blocks, each call requiring a
- certain minimum size. Callers are free to abbreviate the parameter block where
- appropriate.
-
- »General
-
- With each routine, a list of the parameter block fields used by the call is also
- given. All routines are invoked by Device Manager Control calls with the csCode
- field equal to the code corresponding to the function being called. The number next
- to each field name indicates the byte offset of the field from the start of the
- parameter block pointed to by A0; only assembly-language programmers need to be
- concerned with it. An arrow next to each parameter name indicates whether it’s an
- input, output, or input/output parameter:
-
- Arrow Meaning
- <-- Parameter is passed
- <-- Parameter is returned
- <-> Parameter is passed and returned
-
- All Device Manager Control calls return an integer result code in the ioResult field.
- Each routine description lists all the applicable result codes, along with a short
- description of what the result code means. Refer to the section
- “XPP Driver Result Codes” for an alphabetical list of result codes returned by the
- .XPP driver.
-
- Each routine description includes a Pascal form of the call. Pascal calls to the
- .XPP Driver are of the form:
-
- FUNCTION XPPCall (paramBlock: XPPParmBlkPtr,async: BOOLEAN) : OSErr;
-
- XPPCall is the name of the routine.
-
- The parameter paramBlock points to the actual I/O queue element used in the
- _Control call, filled in by the caller with the parameters of the routine.
-
- The parameter async indicates whether or not the call should be made asynchronously.
- If async is TRUE, the call is executed asynchronously; otherwise the call is executed
- synchronously.
-
- The routine returns a result code of type OSErr.
-
- ».XPP Driver Parameter Block Record
-
- XPPParamBlock = PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: INTEGER; {queue type}
- ioTrap: INTEGER; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OSErr; {result code}
- cmdResult: LONGINT; {command result (ATP user bytes) [long]}
- ioVRefNum: INTEGER; {volume reference or drive number)
- ioRefNum: INTEGER; {driver reference number)
- csCode: INTEGER; {Call command code}
- CASE XPPPrmBlkType OF
- ASPAbortPrm:
- (abortSCBPtr: Ptr); {SCB pointer for AbortOS [long]}
- ASPSizeBlk:
- (aspMaxCmdSize: INTEGER; {for SPGetParms [word]
- aspQuantumSize: INTEGER; {for SPGetParms [word]}
- numSesss: INTEGER); {for SPGetParms [word]}
- XPPPrmBlk:
- (sessRefnum: INTEGER; {offset to session refnum [word]}
- aspTimeout: Byte; {timeout for ATP [byte]}
- aspRetry: Byte; {retry count for ATP [byte]}
- CASE XPPSubPrmType OF
- ASPOpenPrm:
- (serverAddr: AddrBlock; {server address block [longword]}
- scbPointer: Ptr; {SCB pointer [longword]}
- attnRoutine: Ptr); {attention routine pointer [long]}
- ASPSubPrm:
- (cbSize: INTEGER; {command block size [word]}
- cbPtr: Ptr; {command block pointer [long]}
- rbSize: INTEGER; {reply buffer size [word]}
- rbPtr: Ptr; {reply buffer pointer [long]}
- CASE XPPEndPrmType OF
- AFPLoginPrm:
- (afpAddrBlock: AddrBlock; {address block in}
- { AFPlogin [long]}
- afpSCBPtr: Ptr; {SCB pointer in }
- { AFPlogin [long]}
- afpAttnRoutine: Ptr); {attn routine pointer }
- { in AFPlogin}
- ASPEndPrm:
- (wdSize: INTEGER; {write data size [word]}
- wdPtr: Ptr; {write data pointer [long]}
- ccbStart: ARRAY[0..295] OF Byte))); {CCB memory }
- { for driver}
- {Write max size(CCB) = 296; all other calls = 150}
- END;
-
- _______________________________________________________________________________
-
- »AppleTalk Session Protocol Functions
-
- This section contains descriptions of the .XPP driver functions that you can call.
- Each function description shows the required parameter block fields, their offsets
- within the parameter block and a brief definition of the field. Possible result
- codes are also described.
-
- »Note on Result Codes
-
- An important distinction exists between the aspParamErr and aspSessClose result
- codes that may be returned by the .XPP driver.
-
- When the driver returns aspParamErr to a call that takes as an input a session reference
- number, the session reference number does not relate to a valid open session. There
- could be several reasons for this, such as the workstation or server end closed the
- session or the server end of the session died.
-
- The aspSessClosed result code indicates that even though the session reference number
- relates to a valid session, that particular session is in the process of closing down
- (although the session is not yet closed).
-
- FUNCTION ASPOpenSession (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 26 csCode word Always ASPOpenSess
- --> 28 sessRefnum word Session reference number
- --> 30 aspTimeout byte Retry interval in seconds
- --> 31 aspRetry byte Number of retries
- --> 32 serverAddr long word Server socket address
- --> 36 scbPointer pointer Pointer to session control block
- --> 40 attnRoutine pointer Pointer to attention routine
-
- ASPOpenSession initiates (opens) a session between the workstation and a server. The
- required parameter block is shown above. A brief definition of the fields follows.
-
- SessRefnum is a unique number identifying the open session between the workstation
- and the server. The SessRefnum is returned when the function completes successfully
- and is used in all calls to identify the session.
-
- ASPTimeOut is the interval in seconds between retries of the open session request.
-
- ASPRetry is the number of retries that will be attempted.
-
- ServerAddr is the network identifier or address of the socket on which the server is
- listening.
-
- SCBPointer points to a nonrelocatable block of data for the session control block
- (SCB) that the .XPP driver reserves for use in maintaining an open session. The SCB
- size is defined by the constant scbMemSize. The SCB is a locked block and as long as
- the session is open, the SCB cannot be modified in any way by the application. There
- is one SCB for each open session. This block can be reused when a CloseSess call is
- issued and completed for that session, or when the session is indicated as closed
- through return of aspParamErr as the result of a call for that session.
-
- AttnRoutine is a pointer to a routine that is invoked if an attention from the server
- is received, or upon session closing. If this pointer is equal to zero, no attention
- routine will be invoked.
-
- Result codes aspNoMoreSess Driver cannot support another session
- aspParamErr Server returned bad (positive) error code
- aspNoServers No servers at that address, or the server
- did not respond to the request
- reqAborted OpenSess was aborted by an AbortOS
- aspBadVersNum Server cannot support the offered
- version number
- aspServerBusy Server cannot open another session
-
- Note: The number of sessions that the driver is capable of supporting
- depends on the machine that the driver is running on.
-
- FUNCTION ASPCloseSession (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 26 csCode word Always ASPCloseSession
- --> 28 sessRefnum word Session reference number
-
- ASPCloseSession closes the session identified by the sessRefnum returned in the
- ASPOpenSession call. ASPCloseSession aborts any calls that are active on the session,
- closes the session, and calls the attention routine, if any, with an attention code
- of zero (zero is invalid as a real attention code).
-
- Result codes aspParamErr Parameter error, indicates an invalid
- session reference number
- aspSessClosed Session already in process of closing
-
- FUNCTION ASPAbortOS (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 26 csCode word Always ASPAbortOS
- --> 28 abortSCBPointer pointer Pointer to session control block
-
- ASPAbortOS aborts a pending (not yet completed) ASPOpenSession call. The aborted
- ASPOpenSession call will return a reqAborted error.
-
- AbortSCBPointer points to the original SCB used in the the pending ASPOpenSession
- call.
-
- Result codes cbNotFound SCB not found, no outstanding open session
- to be aborted.
- Pointer did not point to an open session SCB.
-
- FUNCTION ASPGetParms (xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
-
- Parameter block
- --> 26 csCode word Always ASPGetParms
- --> 28 aspMaxCmdSize word Maximum size of command block
- --> 30 aspQuantumSize word Maximum data size
- --> 32 numSesss word Number of sessions
-
- ASPGetParms returns three ASP parameters. This call does not require an open session.
-
- ASPMaxCmdSize is the maximum size of a command that can be sent to the server.
-
- ASPQuantumSize is the maximum size of data that can be transferred to the server in a
- Write request or from the server in a command reply.
-
- NumSess is the number of concurrent sessions supported by the driver.
-
- FUNCTION ASPCloseAll (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 26 csCode word Always ASPCloseAll
-
- ASPCloseAll closes every session that the driver has active, aborting all active
- requests and invoking the attention routines where provided. This call should be
- used carefully. ASPCloseAll can be used as a system level resource for making sure
- all sessions are closed prior to closing the driver.
-
- FUNCTION ASPUserWrite (xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
-
- Parameter block
- --> 18 cmdResult long word ASP command result
- --> 26 csCode word Always UserWrite
- --> 28 sessRefnum word Session reference number
- --> 30 aspTimeout byte Retry interval in seconds
- --> 32 cbSize word Command block size
- --> 34 cbPtr pointer Command block pointer
- <-> 38 rbSize word Reply buffer size and reply size
- --> 40 rbPtr pointer Reply buffer pointer
- <-> 44 wdSize word Write data size
- --> 46 wdPtr pointer Write data pointer
- --> 50 ccbStart record Start of memory for CCB
-
- ASPUserWrite transfers data on a session. ASPUserWrite is one of the two main calls
- that can be used to transfer data on an ASP session. The other call that performs a
- similar data transfer is ASPUserCommand described below. The ASPUserWrite command
- returns data in two different places. Four bytes of data are returned in the cmdResult
- field and a variable size reply buffer is also returned.
-
- CmdResult is four bytes of data returned by the server.
-
- SessRefnum is the session reference number returned in the ASPOpenSession call.
-
- ASPTimeOut is the interval in seconds between retries of the call. Notice that there
- is no aspRetry field (retries are infinite). The command will be retried at the
- prescribed interval until completion or the session is closed.
-
- CBSize is the size in bytes of the command data that is to be written on the session.
- The size of the command block must not exceed the value of aspMaxCmdSize returned by
- the ASPGetParms call. Note that this buffer is not the data to be written by the
- command but only the data of the command itself.
-
- CBPtr points to the command data.
-
- RBSize is passed and indicates the size of the reply buffer in bytes expected by the
- command. RBSize is also returned and indicates the size of the reply that was actually
- returned.
-
- RBPtr points to the reply buffer.
-
- WDSize is passed and indicates the size of the write data in bytes to be sent by the
- command. WDSize is also returned and indicates the size of the write data that was
- actually written.
-
- WDPointer points to the write data buffer.
-
- CCBStart is the start of the memory to be used by the .XPP driver for the command
- control block. The size of this block is equal to a maximum of 296 bytes. To determine
- the exact requirement, refer to the CCB Sizes section of this document.
-
- Result codes aspParamErr Invalid session number, session has
- been closed
- aspSizeErr Command block size is bigger than MaxCmdSize
- aspSessClosed Session is closing
- aspBufTooSmall Reply is bigger than response buffer;
- the buffer will be filled, data will
- be truncated
-
- FUNCTION ASPUserCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 18 cmdResult long word ASP command result
- --> 26 csCode word Always ASPUserCommand
- --> 28 sessRefnum word Session number
- --> 30 aspTimeout byte Retry interval in seconds
- --> 32 cbSize word Command block size
- --> 34 cbPtr pointer Command block pointer
- <-> 38 rbSize word Reply buffer and reply size
- --> 40 rbPtr pointer Reply buffer pointer
- --> 50 ccbStart record Start of memory for CCB
-
- ASPUserCommand is used to send a command to the server on a session.
-
- SessRefnum is the session reference number returned in the ASPOpenSession call.
-
- ASPTimeOut is the interval in seconds between retries of the call. Notice that there
- is no aspRetry field (retries are infinite). The command will be retried at the
- prescribed interval until completion or the session is closed.
-
- CBSize is the size in bytes of the block of data that contains the command to be sent
- to the server on the session. The size of the command block must not exceed the
- value of aspMaxCmdSize returned by the ASPGetParms call.
-
- CBPointer points to the block of data containing the command that is to be sent to
- the server on the session.
-
- RBSize is passed and indicates the size of the reply buffer in bytes expected by the
- command. RBSize is also returned and indicates the size of the reply that was actually
- returned.
-
- RBPtr points to the reply buffer.
-
- CCBStart is the start of the memory to be used by the .XPP driver for the command
- control block. The size of this block is equal to a maximum of 150 bytes. To determine
- the exact requirement refer to the CCB Sizes section of this document.
-
- Result codes aspParamErr Invalid session number, session has
- been closed
- aspSizeErr Command block size is bigger than MaxCmdSize
- aspSessClosed Session is closing
- aspBufTooSmall Reply is bigger than response buffer;
- the buffer will be filled, data will
- be truncated
-
- FUNCTION ASPGetStatus (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 26 csCode word Always ASPGetStatus
- --> 30 aspTimeout byte Retry interval in seconds
- --> 31 aspRetry byte Number of retries
- --> 32 serverAddr long word Server socket address
- <-> 38 rbSize word Reply buffer and reply size
- --> 40 rbPtr pointer Reply buffer pointer
- --> 50 ccbStart record Start of memory for CCB
-
- ASPGetStatus returns server status. This call is also used as GetServerInfo at the
- AFP level. This call is unique in that it transfers data over the network without
- having a session open. This call does not pass any data but requests that server
- status be returned.
-
- ASPTimeOut is the interval in seconds between retries of the call.
-
- ASPRetry is the number of retries that will be attempted.
-
- ServerAddr is the network identifier or address of the socket on which the server is
- listening.
-
- RBSize is passed and indicates the size of the reply buffer in bytes expected by the
- command. RBSize is also returned and indicates the size of the reply that was actually
- returned.
-
- RBPtr points to the reply buffer.
-
- CCBStart is the start of the memory to be used by the .XPP driver for the command
- control block. The size of this block is equal to a maximum of 150 bytes. To determine
- the exact requirement refer to the CCB Sizes section of this document.
-
- Result codes aspBufTooSmall Reply is bigger than response buffer,
- or Replysize is bigger than ReplyBuffsize
- aspNoServer No response from server at address used
- in call
-
- _______________________________________________________________________________
-
- »AFP Implementation
-
- The AFPCall function (called AFPCommand in Pascal) passes a command to an AFP server.
- The first byte of the AFPCall command buffer (the AFP command byte) must contain a
- valid AFP command code.
-
- Note: Server information should be gotten through an ASPGetStatus call
- (described above). ASPGetStatus is equivalent to the AFPGetSrvrInfo.
- Making an AFP GetSrvrInfo call using AFPCommand results in an error.
-
- »Mapping AFP Commands
-
- Most AFP calls are implemented by XPP through a very simple one-to-one mapping of an
- AFP call to an ASP call without interpretation or verification of the data.
-
- The .XPP driver maps AFP command codes to ASP commands according to the following
- conventions:
-
- AFP Command Code Comment
-
- $00 Invalid AFP command
- $01–$BE (1–190) Mapped to UserCommand (with the exceptions
- listed below)
- $BF (191) Mapped to UserCommand (Reserved for developers;
- will never be used by Apple)
- $C0–$FD (192–253) Mapped to UserWrite
- $FE (254) Mapped to UserWrite (will never be used by Apple)
- $FF (255) Invalid AFP command
-
- The following AFP calls are exceptions to the above conventions:
-
- AFP Command (Code/Decimal) Comment
-
- getSrvrInfo (15) Mapped to ASPGetStatus (Use ASPGetStatus
- to make this call)
- login (18) Mapped to appropriate log-in dialog including
- ASPOpenSession call
- loginCont (19) Mapped to appropriate log-in dialog
- logout (20) Mapped to ASPCloseSession
- write (33) Mapped to ASPUserWrite
-
- The following AFP calls can pass or return more data than can fit in quantumSize
- bytes (eight ATP response packets) and may be broken up by XPP into multiple ASP
- calls.
-
- AFP Command (Code/Decimal) Comment
-
- read (27) Can return up to the number of bytes
- indicated in reqCount
- write (33) Can pass up to the number of bytes
- indicated in reqCount
-
- »AFPCall Function
-
- The AFPCall function can have one of the following command formats.
-
- • General
- • Login
- • AFPWrite
- • AFPRead
-
- »General Command Format
-
- FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 18 cmdResult long word AFP command result
- --> 26 csCode word Always AFPCall
- --> 28 sessRefnum word Session reference number
- --> 30 aspTimeout byte Retry interval in seconds
- --> 32 cbSize word Command buffer size
- --> 34 cbPtr pointer Command buffer
- <-> 38 rbSize word Reply buffer size and reply size
- --> 40 rbPtr pointer Reply buffer pointer
- <-> 44 wdSize word Write data size
- --> 46 wdPtr pointer Write data pointer
- --> 50 ccbStart record Start of memory for CCB
-
- The general command format for the AFPCall function passes an AFP command to the
- server. This format is used for all AFP calls except AFPLogin, AFPRead, and AFPWrite.
- Note that from Pascal this call is referred to as AFPCommand.
-
- CmdResult is four bytes of data returned from the server containing an indication of
- the result of the AFP command.
-
- SessRefnum is the session reference number returned in the AFPLogin call.
-
- ASPTimeOut is the interval in seconds between retries of the call by the driver.
-
- CBSize is the size in bytes of the block of data that contains the command to be sent
- to the server on the session. The size of the command block must not exceed the value
- of aspMaxCmdSize returned by the ASPGetParms call.
-
- CBPtr points to start of the block of data (command block) containing the command
- that is to be sent to the server on the session. The first byte of the command block
- must contain the AFP command byte. Subsequent bytes in the command buffer contain
- the parameters associated with the command as defined in the AFP document.
-
- RBSize is passed and indicates the size of the reply buffer in bytes expected by the
- command. RBSize is also returned and indicates the size of the reply that was actually
- returned.
-
- RBPtr points to the reply buffer.
-
- WDSize is the size of data to be written to the server (only used if the command is
- one that is mapped to an ASPUserWrite).
-
- WDPtr points to the write data buffer (only used if the command is one that is mapped
- to an ASPUserWrite).
-
- CCBStart is the start of the memory to be used by the .XPP driver for the command
- control block. The size of this block is equal to a maximum of 296 bytes. To determine
- the exact requirement refer to the CCB Sizes section of this document.
-
- Result codes aspParamErr Invalid session number; session has
- been closed
- aspSizeErr Command block size is bigger than MaxCmdSize
- aspSessClosed Session is closing
- aspBufTooSmall Reply is bigger than response buffer or
- buffer will be filled, data will be truncated
- afpParmError AFP command block size is equal to zero.
- This error will also be returned if the
- command byte in the command block is equal
- to 0 or $FF (255) or GetSrvrStatus (15).
-
- »Login Command Format
-
- The AFP login command executes a series of AFP operations as defined in the AFP Draft
- Proposal. For further information, refer to the AFP document.
-
- FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
-
- Parameter block
- --> 18 cmdResult long word AFP command result
- --> 26 csCode word Always AFPCall
- --> 28 sessRefnum word Session reference number
- --> 30 aspTimeout byte Retry interval in seconds
- --> 31 aspRetry byte Number of retries
- --> 32 cbSize word Command buffer size
- --> 34 cbPtr pointer Command buffer
- <-> 38 rbSize word Reply buffer size and reply size
- --> 40 rbPtr pointer Reply buffer pointer
- --> 44 afpAddrBlock long word Server address block
- <-> 48 afpSCBPtr pointer SCB pointer
- <-> 52 afpAttnRoutine pointer Attention routine pointer
- --> 50 ccbStart record Start of command control block
-
- CmdResult is four bytes of data returned from the server containing an indication of
- the result of the AFP command.
-
- SessRefnum is the session reference number (returned by the AFPLogin call).
-
- ASPTimeOut is the interval in seconds between retries of the call.
-
- ASPRetry is the number of retries that will be attempted.
-
- CBSize is the size in bytes of the block data that contains the command to be sent to
- the server on the session. The size of the command block must not exceed the value of
- aspMaxCmdSize returned by the ASPGetParms call.
-
- CBPtr points to the block of data (command block) containing the AFP login command
- that is to be sent to the server on the session. The first byte of the command block
- must be the AFP login command byte. Subsequent bytes in the command buffer contain
- the parameters associated with the command.
-
- RBSize is passed and indicates the size of the reply buffer in bytes expected by the
- command. RBSize is also returned and indicates the size of the reply that was actually
- returned.
-
- RBPtr points to the reply buffer.
-
- AFPServerAddr is the network identifier or address of the socket on which the server
- is listening.
-
- AFPSCBPointer points to a locked block of data for the session control block
- (SCB). The SCB size is defined by scbMemSize. The SCB is a locked block, and as long
- as the session is open, the SCB cannot be modified in any way by the application.
- There is one SCB for each open session.
-
- AFPAttnRoutine is a pointer to a routine that is invoked if an attention from the
- server is received. When afpAttnRoutine is equal to zero, no attention routine will
- be invoked.
-
- CCBStart is the start of the memory to be used by the .XPP driver for the command
- control block. The size of this block is equal to a maximum of 150 bytes. To determine
- the exact requirement refer to the CCB Sizes section later in this chapter.
-
- Note: In the parameter block, the afpSCBPointer and the afpAttnRoutine
- fields overlap with the start of the CCB and are modified by the call.
-
- Result codes aspSizeErr Command block size is bigger than MaxCmdSize
- aspBufTooSmall Reply is bigger than response buffer or
- buffer will be filled, data will be truncated
- aspNoServer Server not responding
- aspServerBusy Server cannot open another session
- aspBadVersNum Server cannot support the offered ASP
- version number
- aspNoMoreSess Driver cannot support another session.
-
- »AFPWrite Command Format
-
- The AFPWrite and AFPRead command formats allow the calling application to make AFP-level
- calls that read or write a data block that is larger than a single ASP-level call is
- capable of reading or writing. The maximum number of bytes of data that can be read
- or written at the ASP level is equal to quantumSize.
-
- FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 18 cmdResult long word AFP command result
- --> 26 csCode word Always AFPCall
- --> 28 sessRefnum word Session number
- --> 30 aspTimeout byte Retry interval in seconds
- --> 32 cbSize word Command buffer size
- --> 34 cbPtr pointer Command buffer
- <-> 38 rbSize word Reply buffer size and reply size
- --> 40 rbPtr pointer Reply buffer pointer
- --> 44 wdSize word (used internally)
- <-> 46 wdPtr pointer Write data pointer (updated)
- --> 50 ccbStart record Start of memory for CCB
-
- CmdResult is four bytes of data returned from the server containing an indication of
- the result of the AFP command.
-
- SessRefnum is the session reference number returned in the AFPLogin call.
-
- ASPTimeOut is the interval in seconds between retries of the call.
-
- CBSize is the size in bytes of the block data that contains the command to be sent to
- the server on the session. The size of the command block must not exceed the value
- of aspMaxCmdSize returned by the aspGetParms call.
-
- CBPtr points to the block of data (see command block structure below) containing the
- AFP write command that is to be sent to the server on the session. The first byte of
- the Command Block must contain the AFP write command byte.
-
- RBSize is passed and indicates the size of the reply buffer in bytes expected by the
- command. RBSize is also returned and indicates the size of the reply that was actually
- returned.
-
- RBPtr points to the reply buffer.
-
- WDSize is used internally.
-
- Note: This command does not pass the write data size in the queue element
- but in the command buffer. XPP will look for the size in that buffer.
-
- WDPtr is a pointer to the block of data to be written. Note that this field will be
- updated by XPP as it proceeds and will always point to that section of the data which
- XPP is currently writing.
-
- CCBStart is the start of the memory to be used by the XPP driver for the command
- control block. The size of this block is equal to a maximum of 296 bytes. To determine
- the exact requirement refer to the CCB Sizes section later in this chapter.
-
- Command Block Structure: The AFP write command passes several arguments to XPP in
- the command buffer itself. The byte offsets are relative to the location pointed to
- by cbPtr.
-
- --> 0 cmdByte byte AFP call command byte
- --> 1 startEndFlag byte Start/end Flag
- <-> 4 rwOffset long word Offset within fork to write
- <-> 8 reqCount long word Requested count
-
- CmdByte is the AFP call command byte and must contain the AFP write command code.
-
- StartEndFlag is a one-bit flag (the high bit of the byte) indicating whether the
- rwOffset field is relative to the beginning or the end of the fork (all other bits
- are zero).
-
- 0 = relative to the beginning of the fork
- 1 = relative to the end of the fork
-
- RWOffset is the byte offset within the fork at which the write is to begin.
-
- ReqCount indicates the size of the data to be written and is returned as the actual
- size written.
-
- The rwOffset and reqCount fields are modified by XPP as the write proceeds and will
- always indicate the current value of these fields.
-
- The Pascal structure of the AFP command buffer follows:
-
- AFPCommandBlock = PACKED RECORD
- cmdByte: Byte;
- startEndFlag: Byte;
- forkRefNum: INTEGER; {used by server}
- rwOffset: LONGINT;
- reqCount: LONGINT;
- newLineFlag: Byte; {unused by write}
- newLineChar: CHAR; {unused by write}
- END;
-
- Result codes aspParamErr Invalid session number
- aspSizeErr Command block size is bigger than MaxCmdSize
- aspSessClosed Session is closing
- aspBufTooSmall Reply is bigger than response buffer
-
- »AFPRead Command Format
-
- The AFPWrite and AFPRead command formats allow the calling application to make AFP-level
- calls that read or write a data block that is larger than a single ASP-level call is
- capable of reading or writing. The maximum number of bytes of data that can be read
- or written at the ASP level is equal to quantumSize.
-
- FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- --> 18 cmdResult long word ASP command result
- --> 26 csCode word Always AFPCall
- --> 28 sessRefnum word Session number
- --> 30 aspTimeout byte Retry interval in seconds
- --> 32 cbSize word Command buffer size
- --> 34 cbPtr pointer Command buffer
- --> 38 rbSize word Used internally
- <-> 40 rbPtr pointer Reply buffer pointer (updated)
- --> 50 ccbStart record Start of memory for CCB
-
- CmdResult is four bytes of data returned from the server containing an indication of
- the result of the AFP command.
-
- SessRefnum is the session reference number returned in the AFPLogin call.
-
- ASPTimeOut is the interval in seconds between retries of the call.
-
- CBSize is the size in bytes of the block data that contains the command to be sent to
- the server on the session. The size of the command block must not exceed the value
- of aspMaxCmdSize returned by the GetParms call.
-
- CBPtr points to the block of data (command block) containing the AFP read command
- that is to be sent to the server on the session. The first byte of the command block
- must contain the AFP read command byte. The command block structure is shown below.
-
- RBSize is used internally.
-
- Note: This command does not pass the read size in the queue element but
- in the command buffer. XPP will look for the size in that buffer.
-
- RBPtr points to the reply buffer. Note that this field will be updated by XPP as it
- proceeds and will always point to that section of the buffer that XPP is currently
- reading into.
-
- CCBStart is the start of the memory to be used by the .XPP driver for the command
- control block. The size of this block is equal to a maximum of 150 bytes. To determine
- the exact requirement refer to The CCB Sizes section later in this chapter.
-
- Command Block Structure: The AFP read command passes several arguments to XPP in the
- command buffer itself. The byte offsets are relative to the location pointed to by
- cbPointer.
-
- --> 0 cmdByte byte AFP call command byte
- <-> 4 rwOffset long word Offset within fork to read
- <-> 8 reqCount long word Requested count
- --> 12 newLineFlag byte Newline Flag
- --> 13 newLineChar byte Newline Character
-
- CmdByte is the AFP call command byte and must contain the AFP read command code.
-
- RWOffset is the byte offset within the fork at which the read is to begin.
-
- ReqCount indicates the size of the read data buffer and is returned as the actual
- size read.
-
- The rwOffset and reqCount fields are modified by XPP as the read proceeds and will
- always indicate the current value of these fields.
-
- NewLineFlag is a one-bit flag (the high bit of the byte) indicating whether or not
- the read is to terminate at a specified character (all other bits are zero).
-
- 0 = no Newline Character is specified
- 1 = a Newline Character is specified
-
- NewLineChar is any character from $00 to $FF (inclusive) that, when encountered in
- reading the fork, causes the read operation to terminate.
-
- The Pascal structure of the AFPCommand follows:
-
- AFPCommandBlock = PACKED RECORD
- cmdByte: Byte;
- startEndFlag: Byte; {unused for read}
- forkRefNum: INTEGER; {used by server}
- rwOffset: LONGINT;
- reqCount: LONGINT;
- newLineFlag: Byte;
- newLineChar: CHAR;
- END;
-
- Result codes aspParamErr Invalid session number
- aspSizeErr Command block size is bigger than MaxCmdSize
- aspSessClosed Session is closing
- aspBufTooSmall Reply is bigger than response buffer
-
- _______________________________________________________________________________
-
- »CCB Sizes
-
- The .XPP driver uses the memory provided at the end of the UserWrite, UserCommand,
- and GetStatus functions parameter blocks as an internal command control block (CCB).
- Using the maximum block sizes specified in the call descriptions will provide adequate
- space for the call to execute successfully. However, this section is provided for
- developers who wish to minimize the amount of memory taken up by the CCB in the queue
- element.
-
- Specifically, this memory is used for building data structures to be used in making
- calls to the ATP driver. This includes parameter blocks and buffer data structures
- (BDS). The structure of the BDS is detailed in elsewhere in this chapter. The exact
- size of this memory depends on the size of the response expected, and, in the case of
- UserWrite, on the size of data to be written.
-
- In the UserCommand and GetStatus cases (along with all AFP calls which map to UserCommand),
- a BDS must be set up to hold the response information. The number of entries in this
- BDS is equal to the size of the response buffer divided by the maximum number of data
- bytes per ATP response packet (578), rounded up. As described in the ASP chapter in
- Inside AppleTalk, ASP must ask for an extra response in the case where the response
- buffer is an exact multiple of 578. Of course, no BDS can be larger than eight
- elements. XPP also needs bytes for the queue element to call ATP with, so the minimum
- size of a CCB, as a function of the response buffer size (rbSize) is
-
- bdsSize = MIN (((rbSize DIV 578) + 1),8) * bdsEntrySz
- ccbSize = ioQElSize + 4 + bdsSize
-
- With UserWrite (and AFP calls mapping to UserWrite), XPP must create an additional
- BDS and queue element to use in sending the write data to the server. Therefore the
- minimum size of a UserWrite CCB, as a function of the response buffer and write data
- sizes (rbSize and wdSize) is:
-
- wrBDSSize = MIN (((wdSize DIV 578) + 1),8) * bdsEntrySz
- wrCCBSize = (2 * ioQElSize) + 4 + bdsSize + wrBDSSize
-
- Note: BDSEntrySz is equal to 12; ioQelSize is equal to 50.
-
- _______________________________________________________________________________
-
- ».XPP Driver Result Codes
-
- Result Code Comment Returned by
-
- aspBadVersNum Server cannot support the offered version ASPOpenSession
- number. AFPCall (Login)
-
- aspBufTooSmall Reply is bigger than response buffer. ASPUserWrite
- Buffer will be filled, data may be ASPUserCommand
- truncated. ASPGetStatus
- AFPCall
-
- aspNoMoreSess Driver cannot support another session. ASPOpenSessION
- AFPCall (Login)
-
- aspNoServers No servers at that address. ASPGetStatus
- The server did not respond to the request. ASPOpenSession
- AFPCall (Login)
-
- aspParamErr Parameter error, server returned bad ASPOpenSession
- (positive) error code. ASPCloseSess
- Invalid Session Reference Number. ASPUserWrite
- ASPUserCommand
- AFPCall
-
- aspServerBusy Server cannot open another session. ASPOpenSession
- AFPCall (Login)
-
- aspSessClosed Session already in process of closing. ASPCloseSession
- ASPUserWrite
- ASPUserCommand
- AFPCall
-
- aspSizeErr Command block size is bigger than ASPUserWrite
- maxParamSize. ASPUserCommand
- AFPCall
-
- cbNotFound SCB not found, no outstanding ASPAbortOS
- open session to be aborted. Pointer did
- not point to an open session SCB.
-
- afpParmError AFP Command Block size is less than or AFPCall
- equal to zero. Command byte in the
- Command block is equal to 0 or $FF (255)
- or GetSrvrStatus (15).
-
- reqAborted Open session was aborted by an ASPOpenSession
- Abort Open Session. AFPCall (Login)
-
- _______________________________________________________________________________
-
-
- æKY Protocol…Handlers…and…Socket…Listeners
- æC »PROTOCOL HANDLERS AND SOCKET LISTENERS AppleTalkManager
- _______________________________________________________________________________
-
- This section describes how to write your own protocol handlers and socket listeners.
- If you’re only interested in using the default protocol handlers and socket listeners
- provided by the Pascal interface, you can skip this section. Protocol handlers and
- socket listeners must be written in assembly language because they’ll be called by
- the .MPP driver with parameters in various registers not directly accessible from
- Pascal.
-
- The .MPP and .ATP drivers have been designed to maximize overall throughput while
- minimizing code size. Two principal sources of loss of throughput are unnecessary
- buffer copying and inefficient mechanisms for dispatching (routing) packets between
- the various layers of the network protocol architecture. The AppleTalk Manager completely
- eliminates buffer copying by using simple, efficient dispatching mechanisms at two
- important points of the data reception path: protocol handlers and socket listeners.
- To write your own, you should understand the flow of control in this path.
-
- _______________________________________________________________________________
-
- »Data Reception in the AppleTalk Manager
-
- When the SCC detects an ALAP frame addressed to the particular node (or a broadcast
- frame), it interrupts the Macintosh’s MC68000. An interrupt handler built into the
- .MPP driver gets control and begins servicing the interrupt. Meanwhile, the frame’s
- ALAP header bytes are coming into the SCC’s data reception buffer; this is a three-byte
- FIFO buffer. The interrupt handler must remove these bytes from the SCC’s buffer to
- make room for the bytes right behind; for this purpose, MPP has an internal buffer,
- known as the Read Header Area (RHA), into which it places these three bytes.
-
- The third byte of the frame contains the ALAP protocol type field. If the most significant
- bit of this field is set (that is, ALAP protocol types 128 to 255), the frame is an
- ALAP control frame. Since ALAP control frames are only three bytes long (plus two CRC
- bytes), for such frames the interrupt handler simply confirms that the CRC bytes
- indicate an error-free frame and then performs the specified action.
-
- If, however, the frame being received is a data frame (that is, ALAP protocol types 1
- to 127), intended for a higher layer of the protocol architecture implemented on that
- Macintosh, this means that additional data bytes are coming right behind. The interrupt
- handler must immediately pass control to the protocol handler corresponding to the
- protocol type specified in the third byte of the ALAP frame for continued reception
- of the frame. To allow for such a dispatching mechanism, the ALAP code in MPP maintains
- a protocol table. This consists of a list of currently used ALAP protocol types with
- the memory addresses of their corresponding protocol handlers. To allow MPP to transfer
- control to a protocol handler you’ve written, you must make an appropriate entry in
- the protocol table with a valid ALAP protocol type and the memory address of your
- code module.
-
- To enter your protocol handler into the protocol table, issue the LAPOpenProtocol
- call from Pascal or an AttachPH call from assembly language. Thereafter, whenever an
- ALAP header with your ALAP protocol type is received, MPP will call your protocol
- handler. When you no longer wish to receive packets of that ALAP protocol type, call
- LAPCloseProtocol from Pascal or DetachPH from assembly language.
-
- Warning: Remember that ALAP protocol types 1 and 2 are reserved by DDP
- for the default protocol handler and that types 128 to 255 are
- used by ALAP for its control frames.
-
- A protocol handler is a piece of assembly-language code that controls the reception
- of AppleTalk packets of a given ALAP protocol type. More specifically, a protocol
- handler must carry out the reception of the rest of the frame following the ALAP
- header. The nature of a particular protocol handler depends on the characteristics of
- the protocol for which it was written. In the simplest case, the protocol handler
- simply reads the entire packet into an internal buffer. A more sophisticated protocol
- handler might read in the header of its protocol, and on the basis of information
- contained in it, decide where to put the rest of the packet’s data. In certain cases,
- the protocol handler might, after examining the header corresponding to its own
- protocol, in turn transfer control to a similar piece of code at the next-higher
- level of the protocol architecture (for example, in the case of DDP, its protocol
- handler must call the socket listener of the datagram’s destination socket).
-
- In this way, protocol handlers are used to allow “on the fly” decisions regarding the
- intended recipient of the packets’s data, and thus avoid buffer copying. By using
- protocol handlers and their counterparts in higher layers
- (for instance, socket listeners), data sent over the AppleTalk network is read directly
- from the network into the destination’s buffer.
-
- _______________________________________________________________________________
-
- »Writing Protocol Handlers
-
- When the .MPP driver calls your protocol handler, it has already read the first five
- bytes of the packet into the RHA. These are the three-byte ALAP header and the next
- two bytes of the packet. The two bytes following the header must contain the length
- in bytes of the data in the packet, including these two bytes themselves, but excluding
- the ALAP header.
-
- Note: Since ALAP packets can have at most 600 data bytes, only the lower
- ten bits of this length value are significant.
-
- After determining how many bytes to read and where to put them, the protocol handler
- must call one or both of two functions that perform all the low-level manipulation of
- the SCC required to read bytes from the network. ReadPacket can be called repeatedly
- to read in the packet piecemeal or ReadRest can be called to read the rest of the
- packet. Any number of ReadPacket calls can be used, as long as a ReadRest call is
- made to read the final piece of the packet. This is necessary because ReadRest restores
- state information and verifies that the hardware-generated CRC is correct. An error
- will be returned if the protocol handler attempts to use ReadPacket to read more
- bytes than remain in the packet.
-
- When MPP passes control to your protocol handler, it passes various parameters and
- pointers in the processor’s registers:
-
- Register(s) Contents
-
- A0-A1 SCC addresses used by MPP
- A2 Pointer to MPP’s local variables (discussed below)
- A3 Pointer to next free byte in RHA
- A4 Pointer to ReadPacket and ReadRest jump table
- D1 (word) Number of bytes left to read in packet
-
- These registers, with the exception of A3, must be preserved until ReadRest is called.
- A3 is used as an input parameter to ReadPacket and ReadRest, so its contents may be
- changed. D0, D2, and D3 are free for your use. In addition, register A5 has been
- saved by MPP and may be used by the protocol handler until ReadRest is called. When
- control returns to the protocol handler from ReadRest, MPP no longer needs the data
- in these registers. At that point, standard interrupt routine conventions apply and
- the protocol handler can freely use
- A0-A3 and D0-D3 (they’re restored by the interrupt handler).
-
- D1 contains the number of bytes left to be read in the packet as derived from the
- packet’s length field. A transmission error could corrupt the length field or some
- bytes in the packet might be lost, but this won’t be discovered until the end of the
- packet is reached and the CRC checked.
-
- When the protocol handler is first called, the first five bytes of the packet
- (ALAP destination node ID, source node ID, ALAP protocol type, and length) can be
- read from the RHA. Since A3 is pointing to the next free position in the RHA, these
- bytes can be read using negative offsets from A3. For instance, the ALAP source node
- ID is at –4(A3), the packet’s data length (given in D1) is also pointed to by –2(A3),
- and so on. Alternatively, they can be accessed as positive offsets from the top of
- the RHA. The effective address of the top of the RHA is toRHA(A2), so the following
- code could be used to obtain the ALAP type field:
-
- LEA toRHA(A2),A5 ;A5 points to top of RHA
- MOVE.B lapType(A5),D2 ;load D2 with type field
-
- These methods are valid only as long as SCC interrupts remain locked out (which they
- are when the protocol handler is first called). If the protocol handler lowers the
- interrupt level, another packet could arrive over the network and invalidate the
- contents of the RHA.
-
- •••Refer to Technical Note #201:•••
-
- You can call ReadPacket by jumping through the jump table in the following way:
-
- JSR (A4)
-
- On entry D3: number of bytes to be read (word)
- A3: pointer to a buffer to hold the bytes
- On exit D0: modified
- D1: number of bytes left to read in packet (word)
- D2: preserved
- D3: = 0 if requested number of bytes were read
- <> 0 if error
- A0-A2: preserved
- A3: pointer to one byte past the last byte read
-
- ReadPacket reads the number of bytes specified in D3 into the buffer pointed to by
- A3. The number of bytes remaining to be read in the packet is returned in D1. A3
- points to the byte following the last byte read.
-
- You can call ReadRest by jumping through the jump table in the following way:
-
- JSR 2(A4)
-
- On entry A3: pointer to a buffer to hold the bytes
- D3: size of the buffer (word)
- On exit D0-D1: modified
- D2: preserved
- D3: = 0 if packet was exactly the size of the buffer
- < 0 if packet was (–D3) bytes too large to fit in
- buffer and was truncated
- > 0 if D3 bytes weren't read (packet is smaller
- than buffer)
- A0-A2: preserved
- A3: pointer to one byte past the last byte read
-
- ReadRest reads the remaining bytes of the packet into the buffer whose size is given
- in D3 and whose location is pointed to by A3. The result of the operation is returned
- in D3.
-
- ReadRest can be called with D3 set to a buffer size greater than the packet size;
- ReadPacket cannot (it will return an error).
-
- Warning: Remember to always call ReadRest to read the last part of a
- packet; otherwise the system will eventually crash.
-
- If at any point before it has read the last byte of a packet, the protocol handler
- wants to discard the remaining data, it should terminate by calling ReadRest as
- follows:
-
- MOVEQ #0,D3 ;byte count of 0
- JSR 2(A4) ;call ReadRest
- RTS
-
- Or, equivalently:
-
- MOVEQ #0,D3 ;byte count of 0
- JMP 2(A4) ;JMP to ReadRest, not JSR
-
- In all other cases, the protocol handler should end with an RTS, even if errors were
- detected. If MPP returns an error from a ReadPacket call, the protocol handler must
- quit via an RTS without calling ReadRest at all (in this case it has already been
- called by MPP).
-
- The Z (Zero) condition code is set upon return from these routines to indicate the
- presence of errors (CRC, overrun, and so on). Zero bit set means no error was detected;
- a nonzero condition code implies an error of some kind.
-
- Up to 24 bytes of temporary storage are available in MPP’s RHA. When the protocol
- handler is called, 19 of these bytes are free for its use. It may read several bytes
- (at least four are suggested) into this area to empty the SCC’s buffer and buy some
- time for further processing.
-
- MPP’s globals include some variables that you may find useful. They’re allocated as a
- block of memory pointed to by the contents of the global variable ABusVars, but a
- protocol handler can access them by offsets from A2:
-
- Name Contents
-
- sysLAPAddr This node’s node ID (byte)
- toRHA Top of the Read Header Area (24 bytes)
- sysABridge Node ID of a bridge (byte)
- sysNetNum This node’s network number (word)
- vSCCEnable Status Register (SR) value to re-enable SCC interrupts (word)
-
- Warning: Under no circumstances should your protocol handler modify
- these variables. It can read them to find the node’s ID, its
- network number, and the node ID of a bridge on the AppleTalk internet.
-
- If, after reading the entire packet from the network and using the data in the RHA,
- the protocol handler needs to do extensive post-processing, it can load the value in
- vSCCEnable into the SR to enable interrupts. To allow your programs to run transparently
- on any Macintosh, use the value in vSCCEnable rather than directly manipulating the
- interrupt level by changing specific bits in the SR.
-
- Additional information, such as the driver’s version number or reference number and a
- pointer (or handle) to the driver itself, may be obtained from MPP’s device control
- entry. This can be found by dereferencing the handle in the unit table’s entry corresponding
- to unit number 9; for more information, see the section “The Structure of a Device
- Driver” in the Device Manager chapter.
-
- »Timing Considerations
-
- Once it’s been called by MPP, your protocol handler has complete responsibility for
- receiving the rest of the packet. The operation of your protocol handler is time-critical.
- Since it’s called just after MPP has emptied the SCC’s three-byte buffer, the protocol
- handler has approximately 95 microseconds (best case) before it must call ReadPacket
- or ReadRest. Failure to do so will result in an overrun of the SCC’s buffer and loss
- of packet information. If, within that time, the protocol handler can’t determine
- where to put the entire incoming packet, it should call ReadPacket to read at least
- four bytes into some private buffer (possibly the RHA). Doing this will again empty
- the SCC’s buffer and buy another 95 microseconds. You can do this as often as necessary,
- as long as the processing time between successive calls to ReadPacket doesn’t exceed
- 95 microseconds.
-
- _______________________________________________________________________________
-
- »Writing Socket Listeners
-
- A socket listener is a piece of assembly-language code that receives datagrams delivered
- by the DDP built-in protocol handler and delivers them to the client owning that
- socket.
-
- When a datagram (a packet with ALAP protocol type 1 or 2) is received by the ALAP,
- DDP’s built-in protocol handler is called. This handler reads the DDP header into the
- RHA, examines the destination socket number, and determines whether this socket is
- open by searching DDP’s socket table. This table lists the socket number and corresponding
- socket listener address for each open socket. If an entry is found matching the
- destination socket, the protocol handler immediately transfers control to the appropriate
- socket listener. (To allow DDP to recognize and branch to a socket listener you’ve
- written, call DDPOpenSocket from Pascal or OpenSkt from assembly language.)
-
- At this point, the registers are set up as follows:
-
- Register(s) Contents
-
- A0-A1 SCC addresses used by MPP
- A2 Pointer to MPP’s local variables (discussed above)
- A3 Pointer to next free byte in RHA
- A4 Pointer to ReadPacket and ReadRest jump table
- D0 This packet’s destination socket number (byte)
- D1 Number of bytes left to read in packet (word)
-
- The entire ALAP and DDP headers are in the RHA; these are the only bytes of the
- packet that have been read in from the SCC’s buffer. The socket listener can get the
- destination socket number from D0 to select a buffer into which the packet can be
- read. The listener then calls ReadPacket and ReadRest as described under “Writing
- Protocol Handlers” above. The timing considerations discussed in that section apply
- as well, as do the issues related to accessing the MPP local variables.
-
- The socket listener may examine the ALAP and DDP headers to extract the various
- fields relevant to its particular client’s needs. To do so, it must first examine the
- ALAP protocol type field (three bytes from the beginning of the RHA) to decide whether
- a short (ALAP protocol type=1) or long (ALAP protocol type=2) header has been received.
-
- A long DDP header containing a nonzero checksum field implies that the datagram was
- checksummed at the source. In this case, the listener can recalculate the checksum
- using the received datagram, and compare it with the checksum value. The following
- subroutine can be used for this purpose:
-
- DoChksum ;
- ; D1 (word) = number of bytes to checksum
- ; D3 (word) = current checksum
- ; A1 points to the bytes to checksum
- ;
- CLR.W D0 ;clear high byte
- SUBQ.W #1,D1 ;decrement count for DBRA
- Loop MOVE.B (A1)+,D0 ;read a byte into D0
- ADD.W D0,D3 ;accumulate checksum
- ROL.W #1,D3 ;rotate left one bit
- DBRA D1,Loop ;loop if more bytes
- RTS
-
- Note: D0 is modified by DoChksum.
-
- The checksum must be computed for all bytes starting with the DDP header byte following
- the checksum field up to the last data byte (not including the CRC bytes). The socket
- listener must start by first computing the checksum for the DDP header fields in the
- RHA. This is done as follows:
-
- CLR.W D3 ;set checksum to 0
- MOVEQ #ddpHSzLong-ddpDstNet,D1
- ;length of header part to checksum
- LEA toRHA+lapHdSz+ddpDstNet(A2),A1
- ;point to destination network number
- JSR DoChksum
- ; D3 = accumulated checksum of DDP header part
-
- The socket listener must now continue to set up D1 and A1 for each subsequent portion
- of the datagram, and call DoChksum for each. It must not alter the value in D3.
-
- The situation of the calculated checksum being equal to 0 requires special attention.
- For such packets, the source sends a value of –1 to distinguish them from unchecksummed
- packets. At the end of its checksum computation, the socket listener must examine the
- value in D3 to see if it’s 0. If so, it’s converted to –1 and compared with the
- received checksum to determine whether there was a checksum error:
-
- TST.W D3 ;is calculated value 0?
- BNE.S @1 ;no -- go and use it
- SUBQ.W #1,D3 ;it is 0; make it -1
- @1 CMP.W toRHA+lapHdSz+ddpChecksum(A2),D3
- BNE ChksumError
-
- _______________________________________________________________________________
-
-
- æKY Summary…of…the…AppleTalk…Manager
- æC »SUMMARY OF THE APPLETALK MANAGER AppleTalkManager
- _______________________________________________________________________________
-
- Constants
-
- CONST
- lapSize = 20; {ABusRecord size for ALAP}
- ddpSize = 26; {ABusRecord size for DDP}
- nbpSize = 26; {ABusRecord size for NBP}
- atpSize = 56; {ABusRecord size for ATP}
-
- _______________________________________________________________________________
-
- Data Types
-
- TYPE
- ABProtoType = (lapProto,ddpProto,nbpProto,atpProto);
- ABRecHandle = ^ABRecPtr;
- ABRecPtr = ^ABusRecord;
- ABusRecord =
- RECORD
- abOpcode: ABCallType; {type of call}
- abResult: INTEGER; {result code}
- abUserReference: LONGINT; {for your use}
- CASE ABProtoType OF
- lapProto:
- (lapAddress: LAPAdrBlock; {destination or source node ID}
- lapReqCount: INTEGER; {length of frame data or buffer size in }
- { bytes}
- lapActCount INTEGER; {number of frame data bytes actually }
- { received}
- lapDataPtr: Ptr); {pointer to frame data or pointer to }
- { buffer}
- ddpProto:
- (ddpType: Byte; {DDP protocol type}
- ddpSocket: Byte; {source or listening socket number}
- ddpAddress: AddrBlock; {destination or source socket address}
- ddpReqCount: INTEGER; {length of datagram data or buffer size }
- { in bytes}
- ddpActCount: INTEGER; {number of bytes actually received}
- ddpDataPtr: Ptr; {pointer to buffer}
- ddpNodeID: Byte); {original destination node ID}
- nbpProto:
- (nbpEntityPtr: EntityPtr; {pointer to entity name}
- nbpBufPtr: Ptr; {pointer to buffer}
- nbpBufSize: INTEGER; {buffer size in bytes}
- nbpDataField: INTEGER; {number of addresses or socket }
- { number}
- nbpAddress: AddrBlock; {socket address}
- nbpRetransmitInfo:RetransType); {retransmission information}
- atpProto:
- (atpSocket: Byte; {listening or responding socket number}
- atpAddress: AddrBlock; {destination or source socket address}
- atpReqCount: INTEGER; {request size or buffer size}
- atpDataPtr Ptr; {pointer to buffer}
- atpRspBDSPtr: BDSPtr; {pointer to response BDS}
- atpBitMap: BitMapType; {transaction bit map}
- atpTransID: INTEGER; {transaction ID}
- atpActCount: INTEGER; {number of bytes actually received}
- atpUserData: LONGINT; {user bytes}
- atpXO: BOOLEAN; {exactly-once flag}
- atpEOM: BOOLEAN; {end-of-message flag}
- atpTimeOut: Byte; {retry timeout interval in seconds}
- atpRetries: Byte; {maximum number of retries}
- atpNumBufs: Byte; {number of elements in response BDS or }
- { number of response packets sent}
- atpNumRsp: Byte; {number of response packets received or }
- { sequence number}
- atpBDSSize: Byte; {number of elements in response BDS}
- atpRspUData: LONGINT; {user bytes sent or received in }
- { transaction response}
- atpRspBuf: Ptr; {pointer to response message buffer}
- atpRspSize: INTEGER); {size of response message buffer}
- END;
-
- ABCallType = (tLAPRead,tLAPWrite,tDDPRead,tDDPWrite,tNBPLookup,tNBPConfirm,
- tNBPRegister,tATPSndRequest,tATPGetRequest,tATPSdRsp,tATPAddRsp,
- tATPRequest,tATPResponse);
-
- LAPAdrBlock = PACKED RECORD
- dstNodeID: Byte; {destination node ID}
- srcNodeID: Byte; {source node ID}
- lapProtType: ABByte {ALAP protocol type}
- END;
-
- ABByte = 1..127; {ALAP protocol type}
- AddrBlock = PACKED RECORD
- aNet: INTEGER; {network number}
- aNode: Byte; {node ID}
- aSocket: Byte {socket number}
- END;
-
- BDSPtr = ^BDSType;
- BDSType = ARRAY[0..7] OF BDSElement; {response BDS}
- BDSElement = RECORD
- buffSize: INTEGER; {buffer size in bytes}
- buffPtr: Ptr; {pointer to buffer}
- dataSize: INTEGER; {number of bytes actually received}
- userBytes: LONGINT {user bytes}
- END;
-
- BitMapType = PACKED ARRAY[0..7] OF BOOLEAN;
- EntityPtr = ^EntityName;
- EntityName = RECORD
- objStr: Str32; {object}
- typeStr: Str32; {type}
- zoneStr: Str32 {zone}
- END;
-
- Str32 = STRING[32];
- RetransType =
- PACKED RECORD
- retransInterval: Byte; {retransmit interval in 8-tick units}
- retransCount: Byte {total number of attempts}
- END;
-
- MPPParamBlock = PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: INTEGER; {queue type}
- ioTrap: INTEGER; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OSErr; {result code}
- ioNamePtr: StringPtr; {command result (ATP user bytes) [long]}
- ioVRefNum: INTEGER; {volume reference or drive number}
- ioRefNum: INTEGER; {driver reference number}
- csCode: INTEGER; {call command code AUTOMATICALLY SET}
-
- CASE MPPParmType OF
- LAPWriteParm:
- (filler0:INTEGER;
- wdsPointer:Ptr); {->Write Data Structure}
- AttachPHParm,DetachPHParm:
- (protType:Byte; {ALAP Protocol Type}
- filler1:Byte;
- handler:Ptr); {->protocol handler routine}
- OpenSktParm,CloseSktParm,WriteDDPParm:
- (socket:Byte; {socket number}
- checksumFlag:Byte; {checksum flag}
- listener:Ptr); {->socket listener routine}
- RegisterNameParm,LookupNameParm,ConfirmNameParm,RemoveNameParm:
- (interval:Byte; {retry interval}
- count:Byte; {retry count}
- entityPtr:Ptr; {->names table element or }
- { ->entity name}
- CASE MPPParmType OF
- RegisterNameParm:
- (verifyFlag:Byte; {set if verify needed}
- filler3:Byte);
- LookupNameParm:
- (retBuffPtr:Ptr; {->return buffer}
- retBuffSize:INTEGER; {return buffer size}
- maxToGet:INTEGER; {matches to get}
- numGotten:INTEGER); {matched gotten}
- ConfirmNameParm:
- (confirmAddr:AddrBlock; {->entity}
- newSocket:Byte; {socket number}
- filler4:Byte));
-
- SetSelfSendParm:
- (newSelfFlag:Byte; {self-send toggle flag}
- oldSelfFlag:Byte); {previous self-send state}
- KillNBPParm:
- (nKillQEl:Ptr); {ptr to Q element to cancel}
- END;
-
- ATPParamBlock = PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: INTEGER; {queue type}
- ioTrap: INTEGER; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OSErr; {result code}
- userData: LONGINT; {ATP user bytes [long]}
- reqTID: INTEGER; {request transaction ID}
- ioRefNum: INTEGER; {driver reference number
- csCode: INTEGER; {Call command code }
- { AUTOMATICALLY SET}
- atpSocket: Byte; {currBitMap or socket number}
- atpFlags: Byte; {control information}
- addrBlock: AddrBlock; {source/dest. socket address}
- reqLength: INTEGER; {request/response length}
- reqPointer: Ptr; {-> request/response data}
- bdsPointer: Ptr; {-> response BDS}
- CASE MPPParmType OF
- SendRequestParm,NSendRequestParm:
- (numOfBuffs:Byte; {numOfBuffs}
- timeOutVal:Byte; {timeout interval}
- numOfResps:Byte; {number responses actually received}
- retryCount:Byte; {number of retries}
- intBuff:INTEGER); {used internally for NSendRequest}
- SendResponseParm:
- (filler0:Byte; {number of responses being sent}
- bdsSize:Byte; {number of BDS elements}
- transID:INTEGER); {transaction ID}
- GetRequestParm:
- (bitMap:Byte; {bit map}
- filler1:Byte);
- AddResponseParm:
- (rspNum:Byte; {sequence number}
- filler2:Byte);
- KillSendReqParm,KillGetReqParm:
- (aKillQEl:Ptr); {ptr to Q element to cancel}
- END;
-
- XPPParamBlock = PACKED RECORD
- qLink: QElemPtr; {next queue entry}
- qType: INTEGER; {queue type}
- ioTrap: INTEGER; {routine trap}
- ioCmdAddr: Ptr; {routine address}
- ioCompletion: ProcPtr; {completion routine}
- ioResult: OSErr; {result code}
- cmdResult: LONGINT; {command result (ATP user bytes) [long]}
- ioVRefNum: INTEGER; {volume reference or drive number)
- ioRefNum: INTEGER; {driver reference number)
- csCode: INTEGER; {Call command code}
- CASE XPPPrmBlkType OF
- ASPAbortPrm:
- (abortSCBPtr: Ptr); {SCB pointer for AbortOS [long]}
- ASPSizeBlk:
- (aspMaxCmdSize: INTEGER; {for SPGetParms [word]
- aspQuantumSize: INTEGER; {for SPGetParms [word]}
- numSesss: INTEGER); {for SPGetParms [word]}
- XPPPrmBlk:
- (sessRefnum: INTEGER; {offset to session refnum [word]}
- aspTimeout: Byte; {timeout for ATP [byte]}
- aspRetry: Byte; {retry count for ATP [byte]}
- CASE XPPSubPrmType OF
- ASPOpenPrm:
- (serverAddr: AddrBlock; {server address block [longword]}
- scbPointer: Ptr; {SCB pointer [longword]}
- attnRoutine: Ptr); {attention routine pointer [long]}
- ASPSubPrm:
- (cbSize: INTEGER; {command block size [word]}
- cbPtr: Ptr; {command block pointer [long]}
- rbSize: INTEGER; {reply buffer size [word]}
- rbPtr: Ptr; {reply buffer pointer [long]}
- CASE XPPEndPrmType OF
- AFPLoginPrm:
- (afpAddrBlock: AddrBlock; {address block in}
- { AFPlogin [long]}
- afpSCBPtr: Ptr; {SCB pointer in }
- { AFPlogin [long]}
- afpAttnRoutine: Ptr); {attn routine pointer }
- { in AFPlogin}
- ASPEndPrm:
- (wdSize: INTEGER; {write data size [word]}
- wdPtr: Ptr; {write data pointer [long]}
- ccbStart: ARRAY[0..295] OF Byte))); {CCB memory }
- { for driver}
- {Write max size(CCB) = 296; all other calls = 150}
- END;
-
- AFPCommandBlock = PACKED RECORD
- cmdByte: Byte;
- startEndFlag: Byte;
- forkRefNum: INTEGER; {used by server}
- rwOffset: LONGINT;
- reqCount: LONGINT;
- newLineFlag: Byte; {unused by write}
- newLineChar: CHAR; {unused by write}
- END;
-
- AFPCommandBlock = PACKED RECORD
- cmdByte: Byte;
- startEndFlag: Byte; {unused for read}
- forkRefNum: INTEGER; {used by server}
- rwOffset: LONGINT;
- reqCount: LONGINT;
- newLineFlag: Byte;
- newLineChar: CHAR;
- END;
-
- _______________________________________________________________________________
-
- Routines
-
- Opening and Closing AppleTalk
-
- FUNCTION MPPOpen : OSErr;
- FUNCTION MPPClose : OSErr;
-
- AppleTalk Link Access Protocol
-
- FUNCTION LAPOpenProtocol (theLAPType: ABByte; protoPtr: Ptr) : OSErr;
- FUNCTION LAPCloseProtocol (theLAPType: ABByte) : OSErr;
-
- FUNCTION LAPWrite (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
- <-- abOpcode {always tLAPWrite}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> lapAddress.dstNodeID {destination node ID}
- --> lapAddress.lapProtType {ALAP protocol type}
- --> lapReqCount {length of frame data}
- --> lapDataPtr {pointer to frame data}
-
- FUNCTION LAPRead (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
- <-- abOpcode {always tLAPRead}
- <-- abResult {result code}
- --> abUserReference {for your use}
- <-- lapAddress.dstNodeID {destination node ID}
- <-- lapAddress.srcNodeID {source node ID}
- --> lapAddress.lapProtType {ALAP protocol type}
- --> lapReqCount {buffer size in bytes}
- <-- lapActCount {number of frame data bytes actually received}
- --> lapDataPtr {pointer to buffer}
-
- FUNCTION LAPRdCancel (abRecord: ABRecHandle) : OSErr;
-
- Datagram Delivery Protocol
-
- FUNCTION DDPOpenSocket (VAR theSocket: Byte; sktListener: Ptr) : OSErr;
- FUNCTION DDPCloseSocket (theSocket: Byte) : OSErr;
-
- FUNCTION DDPWrite (abRecord: ABRecHandle; doChecksum: BOOLEAN;
- async: BOOLEAN) : OSErr;
- <-- abOpcode {always tDDPWrite}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> ddpType {DDP protocol type}
- --> ddpSocket {source socket number}
- --> ddpAddress {destination socket address}
- --> ddpReqCount {length of datagram data}
- --> ddpDataPtr {pointer to buffer}
-
- FUNCTION DDPRead (abRecord: ABRecHandle; retCksumErrs: BOOLEAN;
- async: BOOLEAN) : OSErr;
- <-- abOpcode {always tDDPRead}
- <-- abResult {result code}
- --> abUserReference {for your use}
- <-- ddpType {DDP protocol type}
- --> ddpSocket {listening socket number}
- <-- ddpAddress {source socket address}
- --> ddpReqCount {buffer size in bytes}
- <-- ddpActCount {number of bytes actually received}
- --> ddpDataPtr {pointer to buffer}
- <-- ddpNodeID {original destination node ID}
-
- FUNCTION DDPRdCancel (abRecord: ABRecHandle) : OSErr;
-
- AppleTalk Transaction Protocol
-
- FUNCTION PNSendRequest (thePBptr: ATPBPtr; async: BOOLEAN) : OSErr;
- --> 18 userData longword User bytes
- <-- 22 reqTID word Transaction ID used in request
- --> 26 csCode word Always sendRequest
- <-> 28 atpSocket byte Socket to send request on
- or Current bitmap
- <-> 29 atpFlags byte Control information
- --> 30 addrBlock longword Destination socket address
- --> 34 reqLength word Dequest size in bytes
- --> 36 reqPointer pointer Pointer to request data
- --> 40 bdsPointer pointer Pointer to response BDS
- --> 44 numOfBuffs byte Number of responses expected
- --> 45 timeOutVal byte Timeout interval
- <-- 46 numOf Resps byte Number of responses received
- <-> 47 retryCount byte Number of retries
- <-- 48 intBuff word Used internally
-
- FUNCTION PKillSendReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- --> 26 csCode word Always PKillSendReq
- --> 44 aKillQEl pointer Pointer to queue element
-
- FUNCTION PKillGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- --> 26 csCode word Always PKillGetReq
- --> 44 aKillQEl pointer Pointer to queue element
-
- FUNCTION ATPLoad : OSErr;
- FUNCTION ATPUnload : OSErr;
- FUNCTION ATPOpenSocket (addrRcvd: AddrBlock; VAR atpSocket: Byte) : OSErr;
- FUNCTION ATPCloseSocket (atpSocket: Byte) : OSErr;
-
- FUNCTION ATPSndRequest (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
- <-- abOpcode {always tATPSndRequest}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> atpAddress {destination socket address}
- --> atpReqCount {request size in bytes}
- --> atpDataPtr {pointer to buffer}
- --> atpRspBDSPtr {pointer to response BDS}
- --> atpUserData {user bytes}
- --> atpXO {exactly-once flag}
- <-- atpEOM {end-of-message flag}
- --> atpTimeOut {retry timeout interval in seconds}
- --> atpRetries {maximum number of retries}
- --> atpNumBufs {number of elements in response BDS}
- <-- atpNumRsp {number of response packets actually received}
-
- FUNCTION ATPRequest (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
- <-- abOpcode {always tATPRequest}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> atpAddress {destination socket address}
- --> atpReqCount {request size in bytes}
- --> atpDataPtr {pointer to buffer}
- <-- atpActCount {number of bytes actually received}
- --> atpUserData {user bytes}
- --> atpXO {exactly-once flag}
- <-- atpEOM {end-of-message flag}
- --> atpTimeOut {retry timeout interval in seconds}
- --> atpRetries {maximum number of retries}
- <-- atpRspUData {user bytes received in transaction response}
- --> atpRspBuf {pointer to response message buffer}
- --> atpRspSize {size of response message buffer}
-
- FUNCTION ATPReqCancel (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
-
- FUNCTION ATPGetRequest (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
- <-- abOpcode {always tATPGetRequest}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> atpSocket {listening socket number}
- <-- atpAddress {source socket address}
- --> atpReqCount {buffer size in bytes}
- --> atpDataPtr {pointer to buffer}
- <-- atpBitMap {transaction bit map}
- <-- atpTransID {transaction ID}
- <-- atpActCount {number of bytes actually received}
- <-- atpUserData {user bytes}
- <-- atpXO {exactly-once flag}
-
- FUNCTION ATPSndRsp (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
- <-- abOpcode {always tATPSdRsp}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> atpSocket {responding socket number}
- --> atpAddress {destination socket address}
- --> atpRspBDSPtr {pointer to response BDS}
- --> atpTransID {transaction ID}
- --> atpEOM {end-of-message flag}
- --> atpNumBufs {number of response packets being sent}
- --> atpBDSSize {number of elements in response BDS}
-
- FUNCTION ATPAddRsp (abRecord: ABRecHandle) : OSErr;
- <-- abOpcode {always tATPAddRsp}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> atpSocket {responding socket number}
- --> atpAddress {destination socket address}
- --> atpReqCount {buffer size in bytes}
- --> atpDataPtr {pointer to buffer}
- --> atpTransID {transaction ID}
- --> atpUserData {user bytes}
- --> atpEOM {end-of-message flag}
- --> atpNumRsp {sequence number}
-
- FUNCTION ATPResponse (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
- <-- abOpcode {always tATPResponse}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> atpSocket {responding socket number}
- --> atpAddress {destination socket address}
- --> atpTransID {transaction ID)
- --> atpRspUData {user bytes sent in transaction response}
- --> atpRspBuf {pointer to response message buffer}
- --> atpRspSize {size of response message buffer}
-
- FUNCTION ATPRspCancel (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
-
- Name-Binding Protocol
-
- FUNCTION PKillNBP (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- --> 26 csCode word Always PKillNBP
- --> 28 nKillQEl pointer Pointer to queue element
-
- FUNCTION NBPRegister (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
- <-- abOpcode {always tNBPRegister}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> nbpEntityPtr {pointer to entity name}
- --> nbpBufPtr {pointer to buffer}
- --> nbpBufSize {buffer size in bytes}
- --> nbpAddress.aSocket {socket address}
- --> nbpRetransmitInfo {retransmission information}
-
- FUNCTION NBPLookup (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
- <-- abOpcode {always tNBPLookup}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> nbpEntityPtr {pointer to entity name}
- --> nbpBufPtr {pointer to buffer}
- --> nbpBufSize {buffer size in bytes}
- <-> nbpDataField {number of addresses received}
- --> nbpRetransmitInfo {retransmission information}
-
- FUNCTION NBPExtract (theBuffer: Ptr; numInBuf: INTEGER; whichOne: INTEGER;
- VAR abEntity: EntityName; VAR address: AddrBlock) : OSErr;
-
- FUNCTION NBPConfirm (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
- <-- abOpcode {always tNBPConfirm}
- <-- abResult {result code}
- --> abUserReference {for your use}
- --> nbpEntityPtr {pointer to entity name}
- <-- nbpDataField {socket number}
- --> nbpAddress {socket address}
- --> nbpRetransmitInfo {retransmission information}
-
- FUNCTION NBPRemove (abEntity: EntityPtr) : OSErr;
- FUNCTION NBPLoad : OSErr;
- FUNCTION NBPUnload : OSErr;
-
- AppleTalk Session Protocol
-
- FUNCTION ASPOpenSession (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
- --> 26 csCode word Always ASPOpenSession
- <-- 28 sessRefnum word Session reference number
- --> 30 aspTimeout byte Retry interval in seconds
- --> 31 aspRetry byte Number of retries
- --> 32 serverAddr long word Server socket address
- --> 36 scbPointer pointer Pointer to session control block
- --> 40 attnRoutine pointer Pointer to attention routine
-
- FUNCTION ASPCloseSession (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
- --> 26 csCode word Always ASPCloseSess
- --> 28 sessRefnum word Session reference number
-
- FUNCTION ASPAbortOS (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
- --> 26 csCode word Always ASPAbortOS
- --> 28 abortSCBPointer pointer Pointer to session control block
-
- FUNCTION ASPGetParms (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
- --> 26 csCode word Always ASPGetParms
- <-- 28 aspMaxCmdSize word Maximum size of command block
- <-- 30 aspQuantumSize word Maximum data size
- <-- 32 numSesss word Number of sessions
-
- FUNCTION ASPCloseAll (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
- --> 26 csCode word Always ASPCloseAll
-
- FUNCTION ASPUserWrite (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
- <-- 18 cmdResult long word ASP command result
- --> 26 csCode word Always ASPUserWrite
- --> 28 sessRefnum word Session reference number
- --> 30 aspTimeout byte Retry interval in seconds
- --> 32 cbSize word Command block size
- --> 34 cbPtr pointer Command block pointer
- <-> 38 rbSize word Reply buffer size and reply size
- --> 40 rbPointer pointer Reply buffer pointer
- <-> 44 wdSize word Write data size
- --> 46 wdPtr pointer Write data pointer
- <-- 50 ccbStart record Start of memory for CCB
-
- FUNCTION ASPUserCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
- <-- 18 cmdResult long word ASP command result
- <-- 26 csCode word Always ASPUserCommand
- <-- 28 sessRefnum word Session number
- <-- 30 aspTimeout byte Retry interval in seconds
- <-- 32 cbSize word Command block size
- <-- 34 cbPtr pointer Command block pointer
- <-> 38 rbSize word Reply buffer and reply size
- <-- 40 rbPtr pointer Reply buffer pointer
- <-- 50 ccbStart record Start of memory for CCB
-
- FUNCTION ASPGetStatus (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
- <-- 26 csCode word Always ASPGetStatus
- <-- 30 aspTimeout byte Retry interval in seconds
- <-- 31 aspRetry byte Number of retries
- <-- 32 serverAddr long word Server socket address
- <-> 38 rbSize word Reply buffer and reply size
- <-- 40 rbPtr pointer Reply buffer pointer
- <-- 50 ccbStart record Start of memory for CCB
-
- General Command Format
-
- FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
-
- Parameter block
- <-- 18 cmdResult long word AFP command result
- <-- 26 csCode word Always AFPCall
- <-- 28 sessRefnum word Session reference number
- <-- 30 aspTimeout byte Retry interval in seconds
- <-- 32 cbSize word Command buffer size
- <-- 34 cbPtr pointer Command buffer
- <-> 38 rbSize word Reply buffer size and reply size
- <-- 40 rbPtr pointer Reply buffer pointer
- <-> 44 wdSize word Write data size
- <-- 46 wdPtr pointer Write data pointer
- <-- 50 ccbStart record Start of memory for CCB
-
- Login Command Format
-
- FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
- <-- 18 cmdResult long word AFP command result
- <-- 26 csCode word Always AFPCall
- <-- 28 sessRefnum word Session reference number
- <-- 30 aspTimeout byte Retry interval in seconds
- <-- 31 aspRetry byte Number of retries
- <-- 32 cbSize word Command buffer size
- <-- 34 cbPtr pointer Command buffer
- <-> 38 rbSize word Reply buffer size and reply size
- <-- 40 rbPtr pointer Reply buffer pointer
- <-- 44 afpAddrBlock long word Server address block
- <-> 48 afpSCBPtr pointer SCB pointer
- <-> 52 afpAttnRoutine pointer Attention routine pointer
- <-- 50 ccbStart record Start of command control block
-
- AFPWrite Command Format
-
- FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
- <-- 18 cmdResult long word AFP command result
- <-- 26 csCode word Always AFPCall
- <-- 28 sessRefnum word Session number
- <-- 30 aspTimeout byte Retry interval in seconds
- <-- 32 cbSize word Command buffer size
- <-- 34 cbPtr pointer Command buffer
- <-> 38 rbSize word Reply buffer size and reply size
- <-- 40 rbPtr pointer Reply buffer pointer
- <-- 44 wdSize word (used internally)
- <-> 46 wdPtr pointer Write data pointer (updated)
- <-- 50 ccbStart record Start of memory for CCB
-
- Command Block Structure
-
- <-- 0 cmdByte byte AFP call command byte
- <-- 1 startEndFlag byte Start/end Flag
- <-> 4 rwOffset long word Offset within fork to write
- <-> 8 reqCount long word Requested count
-
- AFPRead Command Format
-
- FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
- <-- 18 cmdResult long word ASP command result
- <-- 26 csCode word Always AFPCall
- <-- 28 sessRefnum word Session number
- <-- 30 aspTimeout byte Retry interval in seconds
- <-- 32 cbSize word Command buffer size
- <-- 34 cbPtr pointer Command buffer
- <-- 38 rbSize word Used internally
- <-> 40 rbPtr pointer Reply buffer pointer (updated)
- <-- 50 ccbStart record Start of memory for CCB
-
- Command Block Structure
-
- <-- 0 cmdByte byte AFP call command byte
- <-> 4 rwOffset long word Offset within fork to read
- <-> 8 reqCount long word Requested count
- <-- 12 newLineFlag byte Newline Flag
- <-- 13 newLineChar byte Newline Character
-
- Miscellaneous Routines
-
- FUNCTION GetNodeAddress (VAR myNode,myNet: INTEGER) : OSErr;
- FUNCTION IsMPPOpen : BOOLEAN;
- FUNCTION IsATPOpen : BOOLEAN;
-
- FUNCTION PSetSelfSend (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- --> 26 csCode word Always PSetSelfSend
- --> 28 newSelfFlag byte New SelfSend flag
- <-- 29 oldSelfFlag byte Old SelfSend flag
-
- _______________________________________________________________________________
-
- Result Codes
-
- Name Value Meaning
- atpBadRsp –3107 Bad response from ATPRequest
- atpLenErr –3106 ATP response message too large
- badATPSkt –1099 ATP bad responding socket
- badBuffNum –1100 ATP bad sequence number
- buf2SmallErr –3101 ALAP frame too large for buffer DDP datagram
- too large for buffer
- cbNotFound –1102 ATP control block not found
- cksumErr –3103 DDP bad checksum
- ddpLenErr –92 DDP datagram or ALAP data length too big
- ddpSktErr –91 DDP socket error: socket already active; not a
- well-known socket; socket table full; all dynamic
- socket numbers in use
- excessCollsns –95 ALAP no CTS received after 32 RTS's, or line
- sensed in use 32 times (not necessarily caused
- by collisions)
- extractErr –3104 NBP can't find tuple in buffer
- lapProtErr –94 ALAP error attaching/detaching ALAP protocol type:
- attach error when ALAP protocol type is negative,
- not in range, already in table, or when table is full;
- detach error when ALAP protocol type isn't in table
- nbpBuffOvr –1024 NBP buffer overflow
- nbpConfDiff –1026 NBP name confirmed for different socket
- nbpDuplicate –1027 NBP duplicate name already exists
- nbpNISErr –1029 NBP names information socket error
- nbpNoConfirm –1025 NBP name not confirmed
- nbpNotFound –1028 NBP name not found
- noBridgeErr –93 No bridge found
- noDataArea –1104 Too many outstanding ATP calls
- noErr 0 No error
- noMPPError –3102 MPP driver not installed
- noRelErr –1101 ATP no release received
- noSendResp –1103 ATPAddRsp issued before ATPSndRsp
- portInUse –97 Driver Open error, port already in use
- portNotCf –98 Driver Open error, port not configured
- for this connection
- readQErr –3105 Socket or protocol type invalid or not found in table
- recNotFnd –3108 ABRecord not found
- reqAborted –1105 Request aborted
- reqFailed –1096 ATPSndRequest failed: retry count exceeded
- sktClosedErr –3109 Asynchronous call aborted because socket was
- closed before call was completed
- tooManyReqs –1097 ATP too many concurrent requests
- tooManySkts –1098 ATP too many responding sockets
-
- _______________________________________________________________________________
-
- Assembly-Language Information
-
- Constants
-
- ; Serial port use types
-
- useFree .EQU 0 ;unconfigured
- useATalk .EQU 1 ;configured for AppleTalk
- useASync .EQU 2 ;configured for the Serial Driver
-
- ; Bit in PortBUse for .ATP driver status
-
- atpLoadedBit .EQU 4 ;set if .ATP driver is opened
-
- ; Unit numbers for AppleTalk drivers
-
- mppUnitNum .EQU 9 ;.MPP driver
- atpUnitNum .EQU 10 ;.ATP driver
-
- ; csCode values for Control calls (MPP)
-
- writeLAP .EQU 243
- detachPH .EQU 244
- attachPH .EQU 245
- writeDDP .EQU 246
- closeSkt .EQU 247
- openSkt .EQU 248
- loadNBP .EQU 249
- confirmName .EQU 250
- lookupName .EQU 251
- removeName .EQU 252
- registerName .EQU 253
- killNBP .EQU 254
- unloadNBP .EQU 255
-
- ; csCode values for Control calls (ATP)
-
- relRspCB .EQU 249
- closeATPSkt .EQU 250
- addResponse .EQU 251
- sendResponse .EQU 252
- getRequest .EQU 253
- openATPSkt .EQU 254
- sendRequest .EQU 255
- relTCB .EQU 256
-
- ; ALAP header
-
- lapDstAdr .EQU 0 ;destination node ID
- lapSrcAdr .EQU 1 ;source node ID
- lapType .EQU 2 ;ALAP protocol type
-
- ; ALAP header size
-
- lapHdSz .EQU 3
-
- ; ALAP protocol type values
-
- shortDDP .EQU 1 ;short DDP header
- longDDP .EQU 2 ;long DDP header
-
- ; Long DDP header
-
- ddpHopCnt .EQU 0 ;count of bridges passed (4 bits)
- ddpLength .EQU 0 ;datagram length (10 bits)
- ddpChecksum .EQU 2 ;checksum
- ddpDstNet .EQU 4 ;destination network number
- ddpSrcNet .EQU 6 ;source network number
- ddpDstNode .EQU 8 ;destination node ID
- ddpSrcNode .EQU 9 ;source node ID
- ddpDstSkt .EQU 10 ;destination socket number
- ddpSrcSkt .EQU 11 ;source socket number
- ddpType .EQU 12 ;DDP protocol type
-
- ; DDP long header size
-
- ddpHSzLong .EQU ddpType+1
-
- ; Short DDP header
-
- ddpLength .EQU 0 ;datagram length
- sDDPDstSkt .EQU ddpChecksum ;destination socket number
- sDDPSrcSkt .EQU sDDPDstSkt+1 ;source socket number
- sDDPType .EQU sDDPSrcSkt+1 ;DDP protocol type
-
- ; DDP short header size
-
- ddpHSzShort .EQU sDDPType+1
-
- ; Mask for datagram length
-
- ddpLenMask .EQU $03FF
-
- ; Maximum size of DDP data
-
- ddpMaxData .EQU 586
-
- ; ATP header
-
- atpControl .EQU 0 ;control information
- atpBitMap .EQU 1 ;bit map
- atpRespNo .EQU 1 ;sequence number
- atpTransID .EQU 2 ;transaction ID
- atpUserData .EQU 4 ;user bytes
-
- ; ATP header size
-
- atpHdSz .EQU 8
-
- ; DDP protocol type for ATP packets
-
- atp .EQU 3
-
- ; ATP function code
-
- atpReqCode .EQU $40 ;TReq packet
- atpRspCode .EQU $80 ;TResp packet
- atpRelCode .EQU $C0 ;TRel packet
-
- ; ATPFlags control information bits
-
- sendChk .EQU 0 ;send-checksum bit
- tidValid .EQU 1 ;transaction ID validity bit
- atpSTSBit .EQU 3 ;send-transmission-status bit
- atpEOMBit .EQU 4 ;end-of-message bit
- atpXOBit .EQU 5 ;exactly-once bit
-
- ; Maximum number of ATP request packets
-
- atpMaxNum .EQU 8
-
- ; ATP buffer data structure
-
- bdsBuffSz .EQU 0 ;size of data to send or buffer size
- bdsBuffAddr .EQU 2 ;pointer to data or buffer
- bdsDataSz .EQU 6 ;number of bytes actually received
- bdsUserData .EQU 8 ;user bytes
-
- ; BDS element size
-
- bdsEntrySz .EQU 12
-
- ; NBP packet
-
- nbpControl .EQU 0 ;packet type
- nbpTCount .EQU 0 ;tuple count
- nbpID .EQU 1 ;packet identifier
- nbpTuple .EQU 2 ;start of first tuple
-
- ; DDP protocol type for NBP packets
-
- nbp .EQU 2
-
- ; NBP packet types
-
- brRq .EQU 1 ;broadcast request
- lkUp .EQU 2 ;lookup request
- lkUpReply .EQU 3 ;lookup reply
-
- ; NBP tuple
-
- tupleNet .EQU 0 ;network number
- tupleNode .EQU 2 ;node ID
- tupleSkt .EQU 3 ;socket number
- tupleEnum .EQU 4 ;used internally
- tupleName .EQU 5 ;entity name
-
- ; Maximum number of tuples in NBP packet
-
- tupleMax .EQU 15
-
- ; NBP meta-characters
-
- equals .EQU '=' ;"wild-card" meta-character
- star .EQU '*' ;"this zone" meta-character
-
- ; NBP names table entry
-
- ntLink .EQU 0 ;pointer to next entry
- ntTuple .EQU 4 ;tuple
- ntSocket .EQU 7 ;socket number
- ntEntity .EQU 9 ;entity name
-
- ; NBP names information socket number
-
- nis .EQU 2
-
- Offsets in User Bytes
-
- aspCmdCode EQU 0 ;offset to command field
- aspWSSNum EQU 1 ;WSS number in OpenSessions
- aspVersNum EQU 2 ;ASP version number in OpenSessions
- aspSSSNum EQU 0 ;SSS number in OpenSessReplies
- aspSessID EQU 1 ;session ID (requests &OpenSessReply)
- aspOpenErr EQU 2 ;OpenSessReply error code
-
- aspSeqNum EQU 2 ;sequence number in requests
- aspAttnCode EQU 2 ;attention bytes in attentions
-
- Offsets in ATP data part
-
- aspWrBSize EQU 0 ;offset to write buffer size (WriteData)
- aspWrHdrSz EQU ASPWrBSize+2 ;size of data part
-
- ASP command codes
-
- aspCloseSess EQU 1 ;close session
- aspCommand EQU 2 ;user-command
- aspGetStat EQU 3 ;get status
- aspOpenSess EQU 4 ;open session
- aspTickle EQU 5 ;tickle
- aspWrite EQU 6 ;write
- aspDataWrite EQU 7 ;writedata (from server)
- aspAttention EQU 8 ;attention (from server)
-
- ASP miscellaneous
-
- aspVersion EQU $0100 ;ASP version number
- MaxCmdSize EQU ATPMaxData ;maximum command block size
- QuantumSize EQU ATPMaxData*ATPMaxNum ;maximum reply size
- XPPLoadedBit EQU ATPLoadedBit+1 ;XPP bit in PortBUse
- XPPUnitNum EQU 40 ;unit number for XPP (old ROMs)
-
- ASP errors codes
-
- aspBadVersNum EQU -1066 ;server cannot support this ASP version
- aspBufTooSmall EQU -1067 ;buffer too small
- aspNoMoreSess EQU -1068 ;no more sessions on server
- aspNoServers EQU -1069 ;no servers at that address
- aspParamErr EQU -1070 ;parameter error
- aspServerBusy EQU -1071 ;server cannot open another session
- aspSessClosed EQU -1072 ;session closed
- aspSizeErr EQU -1073 ;command block too big
- aspTooMany EQU -1074 ;too many clients
- aspNoAck EQU -1075 ;no ack on attention Request
-
- Control codes
-
- openSess EQU 255 ;open session
- closeSess EQU 254 ;close session
- userCommand EQU 253 ;user command
- userWrite EQU 252 ;user write
- getStatus EQU 251 ;get status
- afpCall EQU 250 ;AFP command (buffer has command code)
- getParms EQU 249 ;get parameters
- abortOS EQU 248 ;abort open session request
- closeAll EQU 247 ;close all open sessions
-
- ASP queue element standard structure: arguments passed in the CSParam area
-
- sessRefnum EQU $1C ;offset to session refnum [word]
- aspTimeout EQU $1E ;timeout for ATP [byte]
- aspRetry EQU $1F ;retry count for ATP [byte]
- serverAddr EQU $20 ;server address block [longword]
- scbPointer EQU $24 ;SCB pointer [longword]
- attnRoutine EQU $28 ;attention routine pointer [long]
-
- cbSize EQU $20 ;command block size [word]
- cbPtr EQU $22 ;command block pointer [long]
- rbSize EQU $26 ;reply buffer size [word]
- rbPtr EQU $28 ;reply buffer pointer [long]
- wdSize EQU $2C ;write data size [word]
- wdPtr EQU $2E ;write data pointer [long]
- ccbStart EQU $32 ;start of memory for CCB
-
- aspMaxCmdSize EQU $1C ;for SPGetParms [word]
- aspQuantumSize EQU $1E ;for SPGetParms [word]
- abortSCBPtr EQU $1F ;SCB pointer for AbortOS [long]
-
- cmdResult EQU $12 ;command result (ATP user
- ; bytes)[long]
-
- afpAddrBlock EQU $2C ;address block in AFP login[long]
- afpSCBPtr EQU $30 ;SCB pointer in AFP login [long]
- afpAttnRoutine EQU $34 ;attn routine pointer in AFP login
-
- scbMemSize EQU $C0 ;size of memory for SCB
-
- AFPCall command codes
-
- afpLogin EQU 18;
- afpContLogin EQU 19;
- afpLogout EQU 20;
- afpRead EQU 27;
- afpWrite EQU 33;
-
- Offsets for certain parameters in Read/Write calls
-
- startEndFlag EQU $1 ;write only; offset relative to start or end
- rwOffset EQU $4 ;offset at which to start read or write
- reqCount EQU $8 ;count of bytes to read or write
- newLineFlag EQU $C ;read only; newline character flag
- newLineChar EQU $D ;read only; newline character
- lastWritten EQU $0 ;write only; last written (returned)
-
- Miscellaneous
-
- afpUseWrite EQU $C0 ;first call in range that maps to an
- ; ASPWrite
-
- Routines
-
- Preferred Interface Routines
-
- AttachPH Function PAttachPH (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- DetachPH Function PDetachPH (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- WriteLAP Function PWriteLAP (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- OpenSkt Function POpenSkt (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- CloseSkt Function PCloseSkt (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- WriteDDP Function PWriteDDP (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- RegisterName Function PRegisterName(thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- LookupName Function PLookupName (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- ConfirmName Function PConfirmName (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- RemoveName Function PRemoveName (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- OpenATPSkt Function POpenATPSkt (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- CloseATPSkt Function PCloseATPSkt (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- SendRequest Function PSendRequest (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- GetRequest Function PGetRequest (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- SendResponse Function PSendResponse(thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- AddResponse Function PAddResponse (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- ReLTCB Function PRelTCB (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- RelRspCB Function PRelRspCB (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- SetSelfSend Function PSetSelfSend (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
- NSendRequest Function PNSendRequest(thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- KillSendReq Function PKillSendReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- KillGetReq Function PKillGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
- KillNBP Function PKillNBP (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
-
- PROCEDURE BuildLAPwds (wdsPtr,dataPtr: Ptr;
- destHost,protoType,frameLen: INTEGER);
- PROCEDURE BuildDDPwds (wdsPtr,headerPtr,dataPtr: Ptr; destAddress: AddrBlock;
- DDPType : INTEGER; dataLen: INTEGER);
- PROCEDURE NBPSetEntity (buffer: Ptr; nbpObject,nbpType,nbpZone: Str32);
- PROCEDURE NBPSetNTE (ntePtr: Ptr; nbpObject,nbpType,nbpZone: Str32;
- Socket: INTEGER);
- FUNCTION NBPExtract (theBuffer: Ptr; numInBuf: INTEGER; whichOne: INTEGER;
- VAR abEntity: EntityName; VAR address: AddrBlock) : OSErr;
- FUNCTION GetBridgeAddress: INTEGER;
- FUNCTION BuildBDS (buffPtr,bdsPtr: Ptr; buffSize: INTEGER) : INTEGER;
-
- Alternate Interface Routines
-
- Link Access Protocol
-
- WriteLAP function
- --> 26 csCode word ;always writeLAP
- --> 30 wdsPointer pointer ;write data structure
-
- AttachPH function
- --> 26 csCode word ;always attachPH
- --> 28 protType byte ;ALAP protocol type
- --> 30 handler pointer ;protocol handler
-
- DetachPH function
- --> 26 csCode word ;always detachPH
- --> 28 protType byte ;ALAP protocol type
-
- Datagram Delivery Protocol
-
- OpenSkt function
- --> 26 csCode word ;always openSkt
- <-> 28 socket byte ;socket number
- --> 30 listener pointer ;socket listener
-
- CloseSkt function
- --> 26 csCode word ;always closeSkt
- --> 28 socket byte ;socket number
-
- WriteDDP function
- --> 26 csCode word ;always writeDDP
- --> 28 socket byte ;socket number
- --> 29 checksumFlag byte ;checksum flag
- --> 30 wdsPointer pointer ;write data structure
-
- AppleTalk Transaction Protocol
-
- OpenATPSkt function
- --> 26 csCode word ;always openATPSkt
- <-> 28 atpSocket byte ;socket number
- --> 30 addrBlock long word ;socket request specification
-
- CloseATPSkt function
- --> 26 csCode word ;always closeATPSkt
- --> 28 atpSocket byte ;socket number
-
- SendRequest function
- --> 18 userData long word ;user bytes
- <-- 22 reqTID word ;transaction ID used in request
- --> 26 csCode word ;always sendRequest
- <-- 28 currBitMap byte ;bit map
- <-> 29 atpFlags byte ;control information
- --> 30 addrBlock long word ;destination socket address
- --> 34 reqLength word ;request size in bytes
- --> 36 reqPointer pointer ;pointer to request data
- --> 40 bdsPointer pointer ;pointer to response BDS
- --> 44 numOfBuffs byte ;number of responses expected
- --> 45 timeOutVal byte ;timeout interval
- <-- 46 numOfResps byte ;number of responses received
- <-> 47 retryCount byte ;number of retries
-
- GetRequest function
- <-- 18 userData long word ;user bytes
- --> 26 csCode word ;always getRequest
- --> 28 atpSocket byte ;socket number
- <-- 29 atpFlags byte ;control information
- <-- 30 addrBlock long word ;source of request
- <-> 34 reqLength word ;request buffer size
- --> 36 reqPointer pointer ;pointer to request buffer
- <-- 44 bitMap byte ;bit map
- <-- 46 transID word ;transaction ID
-
- SendResponse function
- <-- 18 userData long word ;user bytes from TRel
- --> 26 csCode word ;always sendResponse
- --> 28 atpSocket byte ;socket number
- --> 29 atpFlags byte ;control information
- --> 30 addrBlock long word ;response destination
- --> 40 bdsPointer pointer ;pointer to response BDS
- --> 44 numOfBuffs byte ;number of response packets being sent
- --> 45 bdsSize byte ;BDS size in elements
- --> 46 transID word ;transaction ID
-
- AddResponse function
- --> 18 userData long word ;user bytes
- --> 26 csCode word ;always addResponse
- --> 28 atpSocket byte ;socket number
- --> 29 atpFlags byte ;control information
- --> 30 addrBlock long word ;response destination
- --> 34 reqLength word ;response size
- --> 36 reqPointer pointer ;pointer to response
- --> 44 rspNum byte ;sequence number
- --> 46 transID word ;transaction ID
-
- RelTCB function
- --> 26 csCode word ;always relTCB
- --> 30 addrBlock long word ;destination of request
- --> 46 transID word ;transaction ID of request
-
- RelRspCB function
- --> 26 csCode word ;always relRspCB
- --> 28 atpSocket byte ;socket number that request was
- ; received on
- --> 30 addrBlock long word ;source of request
- --> 46 transID word ;transaction ID of request
-
- Name-Binding Protocol
-
- RegisterName function
- --> 26 csCode word ;always registerName
- --> 28 interval byte ;retry interval
- <-> 29 count byte ;retry count
- --> 30 ntQElPtr pointer ;names table element pointer
- --> 34 verifyFlag byte ;set if verify needed
-
- LookupName function
- --> 26 csCode word ;always lookupName
- --> 28 interval byte ;retry interval
- <-> 29 count byte ;retry count
- --> 30 entityPtr pointer ;pointer to entity name
- --> 34 retBuffPtr pointer ;pointer to buffer
- --> 38 retBuffSize word ;buffer size in bytes
- --> 40 maxToGet word ;matches to get
- <-- 42 numGotten word ;matches found
-
- ConfirmName function
- --> 26 csCode word ;always confirmName
- --> 28 interval byte ;retry interval
- <-> 29 count byte ;retry count
- --> 30 entityPtr pointer ;pointer to entity name
- --> 34 confirmAddr pointer ;entity address
- <-- 38 newSocket byte ;socket number
-
- RemoveName function
- --> 26 csCode word ;always removeName
- --> 30 entityPtr pointer ;pointer to entity name
-
- LoadNBP function
- --> 26 csCode word ;always loadNBP
-
- UnloadNBP function
- --> 26 csCode word ;always unloadNB
-
- Variables
-
- SPConfig Use types for serial ports (byte)
- (bits 0-3: current configuration of serial port B
- bits 4-6: current configuration of serial port A)
- PortBUse Current availability of serial port B (byte)
- (bit 7: 1 = not in use, 0 = in use bits
- bits 0-3: current use of port bits
- bits 4-6: driver-specific)
- ABusVars Pointer to AppleTalk variables
-
- Further Reference:
- _______________________________________________________________________________
- Toolbox Event Manager
- Device Manager
- Technical Note #9, Will Your AppleTalk Application Support Internets?
- Technical Note #20, Data Servers on AppleTalk
- Technical Note #121, Using the High-Level AppleTalk Routines
- Technical Note #132, AppleTalk Interface Update
- Technical Note #142, Avoid Use of Network Events
- Technical Note #195, ASP and AFP Description Discrepancies
- Technical Note #199, KillNBP Clarification
- Technical Note #201, ReadPacket Clarification
- Technical Note #224, Opening AppleTalk
- Technical Note #225, Using RegisterName
- Technical Note #250, AppleTalk Phase 2 on the Macintosh
- “Inside AppleTalk”
-
- æKY BinaryDecimalConversion
- æC
- THE BINARY-DECIMAL CONVERSION PACKAGE
- _______________________________________________________________________________
-
- About…The…Binary-DecimalConversion…Chapter
- Binary-Decimal…Conversion…Package…Routines
- Summary…of…the…Binary-Decimal…Conversion…Package
- _______________________________________________________________________________
-
-
-
- æKY About…The…Binary-DecimalConversion…Chapter
- æC »ABOUT THIS CHAPTER BinaryDecimalConversion
- _______________________________________________________________________________
-
- This chapter describes the Binary-Decimal Conversion Package, which contains five
- routines. One converts an integer from its internal (binary) form to a string that
- represents its decimal (base 10) value; the other converts a decimal string to the
- corresponding integer.
-
- Three new routines have been added to the Binary-Decimal Conversion Package for the
- Macintosh Plus. These routines supplement the Floating-Point Arithmetic and Transcendental
- Functions Packages in providing the the Standard Apple Numeric Environment (SANE) for
- the Macintosh.
-
- Detailed documentation for these new routines is included with the rest of the SANE
- documentation in the Apple Numerics Manual—in particular, see the chapter
- “Conversions” in Part I and the three chapters “Conversions”, “Numeric Scanner and
- Formatter”, and “Examples” in Part III.
-
- The new routines, two numeric scanners and a numeric formatter, are intended for
- programmers with special needs beyond what their development language provides. For
- example, developers of programming languages can use these routines to implement the
- floating-point I/O routines—such as read and write for Pascal or scanf and printf for
- C—that are appropriate for their particular languages. The scanners can be used for
- scanning numbers embedded in text and for numbers received character by character.
- The scanners differ only in that one accepts a pointer to a Pascal strings (with an
- initial length byte) as input, while the other accepts a pointer to the first character
- of a character stream.
-
- The scanners convert ASCII string representations of numbers into SANE decimal records.
- The formatter converts SANE decimal records into ASCII string representations. The
- Floating-Point Arithmetic Package converts between this decimal record format and the
- SANE binary data formats.
-
- The three routines handle the usual number representations, like –1.234 and
- 5e–7, throughout the range and precision of the extended data format. They also
- handle the special NaN, infinity, and signed-zero representations specified by the
- IEEE Floating-Point Standard.
-
- You should already be familiar with packages in general, as described in the Package
- Manager chapter.
-
- _______________________________________________________________________________
-
-
- æKY Binary-Decimal…Conversion…Package…Routines
- æC »BINARY-DECIMAL CONVERSION PACKAGE ROUTINES BinaryDecimalConversion
- _______________________________________________________________________________
-
- The Binary-Decimal Conversion Package is contained in the ROM, beginning with the
- 128K ROM. The routines are register-based, so the Pascal form of each is followed by
- a box containing information needed to use the routine from assembly language.
-
- Assembly-language note: The trap macro for the Binary-Decimal Conversion
- Package is _Pack7. The routine selectors are as
- follows:
-
- numToString .EQU 0
- stringToNum .EQU 1
-
- PROCEDURE NumToString (theNum: LONGINT; VAR theString: Str255);
-
- On entry A0: pointer to theString (preceded by length byte)
- D0: theNum (long word)
- On exit A0: pointer to theString
-
- NumToString converts theNum to a string that represents its decimal value, and returns
- the result in theString. If the value is negative, the string begins with a minus
- sign; otherwise, the sign is omitted. Leading zeroes are suppressed, except that the
- value 0 produces '0'. For example:
-
- theNum theString
-
- 12 '12'
- –23 '–23'
- 0 '0'
-
- PROCEDURE StringToNum (theString: Str255; VAR theNum: LONGINT);
-
- On entry A0: pointer to theString (preceded by length byte)
- On exit D0: theNum (long word)
-
- Given a string representing a decimal integer, StringToNum converts it to the corresponding
- integer and returns the result in theNum. The string may begin with a plus or minus
- sign. For example:
-
- theString theNum
-
- '12' 12
- '–23' –23
- '–0' 0
- '055' 55
-
- The magnitude of the integer is converted modulo 2^32, and the 32-bit result is
- negated if the string begins with a minus sign; integer overflow occurs if the magnitude
- is greater than 2^31–1. (Negation is done by taking the two’s complement—reversing
- the state of each bit and then adding 1.) For example:
-
- theString theNum
-
- '2147483648' (magnitude is 2^31) –2147483648
- '–2147483648' –2147483648
- '4294967295' (magnitude is 2^32–1) –1
- '–4294967295' 1
-
- StringToNum doesn’t actually check whether the characters in the string are between
- '0' and '9'; instead, since the ASCII codes for '0' through '9' are $30 through $39,
- it just masks off the last four bits and uses them as a digit. For example, '2:' is
- converted to the number 30 because the ASCII code for ':' is $3A. Spaces are treated
- as zeroes, since the ASCII code for a space is $20. Given that the ASCII codes for
- 'C', 'A', and 'T' are $43, $41, and $54, respectively, consider the following examples:
-
- theString theNum
-
- 'CAT' 314
- '+CAT' 314
- '–CAT' –314
-
- _______________________________________________________________________________
-
-
- æKY Summary…of…the…Binary-Decimal…Conversion…Package
- æC »SUMMARY OF THE BINARY-DECIMAL CONVERSION PACKAGE BinaryDecimalConversion
- _______________________________________________________________________________
-
- Routines
-
- PROCEDURE NumToString (theNum: LONGINT; VAR theString: Str255);
- PROCEDURE StringToNum (theString: Str255; VAR theNum: LONGINT);
-
- _______________________________________________________________________________
-
- Assembly-Language Information
-
- Constants
-
- ; Routine selectors
-
- numToString .EQU 0
- stringToNum .EQU 1
-
- Routines
-
- Name On entry On exit
-
- NumToString A0: ptr to theString A0: ptr to theString
- (preceded by length byte)
- D0: theNum (long)
- StringToNum A0: ptr to theString D0: theNum (long)
- (preceded by length byte)
-
- Trap Macro Name
-
- _Pack7
-
-
- æKY ColorManager
- æC
- THE COLOR MANAGER
- _______________________________________________________________________________
-
- About…The…ColorManager…Chapter
- About…the…Color…Manager
- Using…the…Color…Manager
- Color…Manager…Routines
- Custom…Search…and…Complement…Functions
- Summary…of…the…Color…Manager
- _______________________________________________________________________________
-
-
-
- æKY About…The…ColorManager…Chapter
- æC »ABOUT THIS CHAPTER ColorManager
- _______________________________________________________________________________
-
- The Color Manager supplies color-selection support for Color QuickDraw on the Macintosh
- II. The software described in this chapter allows specialized applications to fine-tune
- the color-matching algorithms, and also provides utility functions that are rarely
- used by applications.
-
- An understanding of Color QuickDraw concepts, terminology, and data structures is
- essential when using the material in this chapter. You should be familiar with RGB
- color, pixel maps, pixel patterns, and other material introduced in the Color QuickDraw
- chapter. You should also be familiar with the material in the Graphics Devices chapter,
- since the Color Manager routines work on the device level.
-
- Keep in mind that Color Manager routines are the intermediary between high-level
- software such as Color QuickDraw, the Palette Manager, and the Color Picker, and the
- lower-level video devices. The majority of applications will never need to use the
- Color Manager routines directly.
-
- Reader’s guide: The material in this chapter is largely for informational
- purposes only, since Color QuickDraw, the Palette Manager,
- and the other color Toolbox routines provide a detailed and
- consistent way to add color to Macintosh programs.
-
- _______________________________________________________________________________
-
-
- æKY About…the…Color…Manager
- æC »ABOUT THE COLOR MANAGER ColorManager
- _______________________________________________________________________________
-
- The Color Manager is optimized to work with graphics hardware that utilizes a Color
- Look-up Table (CLUT), a data structure that maps color indices, specified using
- QuickDraw, into actual color values. The exact color capabilities of the Macintosh
- II depend on the particular video card used. There are three kinds of devices:
-
- • CLUT devices contain hardware that converts an arbitrary pixel value
- stored in the frame buffer to some actual RGB video value, which is
- changeable. The pixel value could be the index to any of the colors
- in the current color set for the device, and the color set itself
- can be changed.
- • Fixed devices also convert a pixel value to some actual RGB video
- value, but the hardware colors can’t be changed. The pixel value
- could be the index to any of the colors in the color set, but the
- color set itself always remains the same.
- • Direct devices have a direct correlation between the value placed in
- the frame buffer and the color you see on the screen. The value placed
- in the frame buffer would produce the same color every time. Direct
- devices aren’t supported in the initial release of Color QuickDraw.
-
- Applications that limit themselves to a small set of colors can use them simply and
- easily from QuickDraw, with a minimum of overhead. Color QuickDraw accesses the
- Color Manager to obtain the best available color matches in the lookup table. Applications
- such as color painting and animation programs, which need greater control over the
- precise colors they use, can use the Palette Manager to allocate part of the color
- table for their own exclusive use. The Palette Manager, described in a later chapter,
- is useful for most applications that use shared color resources, imaging, or color
- table animation. The Palette Manager is used whenever color is used for objects
- within windows, while the Color Manager operates on the device level.
-
- Note: Palette Manager routines operate transparently across multiple
- screens, while Color Manager routines do not. Therefore, always
- use Palette Manager routines for applications that will run on
- multiple screens or in a multitasking environment.
-
- The sections that follow describe how the Color Manager converts the RGB values
- specified using Color QuickDraw into the actual colors available on a device. The
- pixel value, specifying the number of bits per pixel, is set using the Control Panel.
-
- _______________________________________________________________________________
-
- »Graphics Devices
-
- As with Color QuickDraw, the Color Manager accesses a particular graphics device
- through a data structure known as a gDevice record. Each gDevice record stores information
- about a particular graphics device; after this record is initialized, the device
- itself is known to the Color Manager and QuickDraw as a gDevice. See the Graphics
- Devices chapter for more details on gDevice format and on the routines that allow an
- application to access a given device. Remember that a gDevice is a logical device,
- which the software treats the same whether it is a video card, a display device, or
- an offscreen pixel map.
-
- _______________________________________________________________________________
-
- »Color Table Format
-
- The complete set of colors in use at a given time for a particular gDevice is summarized
- in a color table record. Its format is as follows:
-
- TYPE
- CTabHandle = ^CTabPtr;
- CTabPtr = ^ColorTable;
- ColorTable = RECORD
- ctSeed: LONGINT; {unique identifier from table}
- ctFlags: INTEGER; {high bit is set for a gDevice, }
- { clear for a pixMap}
- ctSize: INTEGER; {Number of entries in table-1}
- ctTable: cSpecArray
- END;
-
- Field descriptions
-
- ctSeed The ctSeed field is similar to a version identifier number for
- a color table. If a color table is created by an application, it
- should call GetCTSeed to obtain this identifier. The ctSeed should
- be some unique number higher than minSeed, a predefined constant
- with a value of 1023. If a color table is created from a resource,
- its resource number will be used as the initial ctSeed. For 'CLUT'
- resource, the range of resource numbers should be 0–1023.
-
- ctFlags The ctFlags field is significant for gDevices only. It contains
- flags that describe the format of the ctTable. Currently, only
- the high bit is defined; all others are reserved. Color tables
- that are part of the gDevice structure always have this bit set.
- Color tables that are part of pixMaps have this bit clear. Each
- gDevice has its own pixMap, which has a color table.
-
- ctSize The ctSize field contains the number of entries in the color
- table minus one. All counts on color table entries are zero based.
-
- ctTable The ctTable field contains a cSpecArray, which is an array of
- ColorSpec entries. Notice that each entry in the color table is
- a ColorSpec, not simply an RGBColor. The type ColorSpec is
- composed of an integer value and an RGB color, as shown in the
- following specification. A color table may include a number of
- ColorSpec records.
-
- TYPE
- cSpecArray = ARRAY [0..0] OF ColorSpec;
- ColorSpec = RECORD
- value : INTEGER; {Color representation}
- rgb : RGBColor {Color value}
- END;
- RGBColor = RECORD
- red : INTEGER; {Red component}
- green : INTEGER; {Green component}
- blue : INTEGER {Blue component}
- END;
-
- In gDevice color tables, the colorSpec.value field is reserved for use by the Color
- Manager and Palette Manager. Their interpretation and values are different than the
- color tables contained in pixMaps.
-
- •••Refer to Figure 1.•••
-
- Figure 1–Color Table Format
-
- Note that the colorSpec.value field of the record is only word size (16 bits), even
- though color index values (as returned by Color2Index) may be long words. The current
- implementation of Color QuickDraw only supports 16 bits. The components in an RGBColor
- are left-justified rather than right-justified in a word. Video drivers should respect
- this convention and extract the appropriate number of bits from the high order side
- of the component. For example, the Apple Graphics Card uses only the most significant
- eight bits of each component of the RGBColor record.
-
- _______________________________________________________________________________
-
- »Inverse Tables
-
- Reader’s guide: The material in this section is provided for informational
- and debugging purposes, since most programs won’t need to
- use inverse tables.
-
- For normal drawing, Color QuickDraw takes all specifications as absolute RGB triples,
- by means of the RGBColor record. Internally, these absolute specifications are converted
- to the appropriate values to be written into the video card. For direct devices, the
- RGB is separated into its red, green, and blue components, and each of these is
- written to the video card. On CLUT and fixed devices, however, there isn’t always a
- direct relationship between the specified RGB and the index value written into the
- frame buffer; in fact, on CLUT devices, the best-match index value may change dynamically
- as the colors available in the hardware are changed. On these types of devices, Color
- QuickDraw uses the Color Manager to find the best matches among the colors currently
- available.
-
- The method used to determine the best available match can be specified by the application
- or the system on a gDevice by gDevice basis. By default, on CLUT and fixed devices, a
- special data structure called an inverse table is created. An inverse table is a
- table arranged in such a manner that, given an arbitrary RGB color, the pixel value
- can be very rapidly looked up.
-
- In the default case, a certain number of the most significant bits of red, green, and
- blue are extracted, then concatenated together to form an index into the inverse
- table. At this location is the “best” match to the specified color. The number of
- bits per color channel that are used to construct this index is known as the resolution
- of the inverse table, and can be 3, 4, or 5 bits per channel. As the resolution of
- the inverse table increases, the number of permutations of possible colors increases,
- as does the size of the inverse table. Three-bit tables occupy 512 bytes, 4-bit
- tables (the default) occupy 4K bytes, and 5-bit tables occupy 32K bytes.
-
- A disadvantage of this method is that certain colors that are “close” together can
- become hidden when they differ only in bits that weren’t used to construct the inverse
- table index. For example, even if the color table were loaded with 256 levels of
- gray, a 4-bit inverse table can only discriminate among 16 of the levels. To solve
- this problem without having to use special-case sets of colors with hidden colors,
- inverse tables carry additional information about how to find colors that differ only
- in the less significant bits. As a result, when the Color2Index routine is called, it
- can find the best match to the full 48-bit resolution available in a colorSpec. Since
- examining the extra information takes time, certain parts of Color QuickDraw, notably
- drawing in the arithmetic transfer modes, don’t use this information, and hence won’t
- find the hidden colors.
-
- In most cases, when setting colors using RGBForeColor and RGBBackColor, and when
- using CopyBits to transfer pixMaps, inverse tables of four bits are sufficient. When
- using arithmetic transfer modes with certain color tables that have closely-spaced
- colors, the screen appearance may be improved by specifying inverse tables at 5-bit
- resolution. Because the format of inverse tables is subject to change in the future,
- or may not be present on certain devices, applications should not assume the structure
- of the data.
-
- The data in inverse tables remains valid as long as the color table from which it was
- built remains unchanged. When a color table is modified, the inverse table must be
- rebuilt, and the screen should be redrawn to take advantage of this new information.
- Rather than being reconstructed when the color table is changed, the inverse table is
- marked invalid, and is automatically rebuilt when next accessed.
-
- Rather than testing each entry of the color table to see if it has changed, the
- color-matching code compares the ctSeed of the current gDevice’s colorTable against
- the iTabSeed of that gDevice’s inverse table. Each routine that modifies the colorTable
- (with the exception of RestoreEntries) increments the ctSeed field of that colorTable.
- If the ctSeed and the iTabSeed don’t match, the inverse table is reconstructed for
- that gDevice.
-
- Note: Under normal circumstances, all invalidations are posted and serviced
- transparently to the application. This method of invalidation is the
- same as that used to invalidate expanded patterns and cursors elsewhere
- in Color QuickDraw.
-
- In certain cases, it may be useful to override the inverse table matching code with
- custom routines that have special matching rules. See the section titled
- “Custom Search and Complement Procedures” for more details.
-
- The Color Manager performs a color table look-up in the following manner:
-
- 1. Builds a table of all possible RGB values;
- 2. For each position in the table, attempts to get the closest match;
- 3. Reduces the resolution of the lookup to four bits when constructing
- the table, but later adds information to get a better resolution.
-
- The Color Manager performs this table-building sequence whenever colors are requested
- by Color QuickDraw, the Color Picker, or the Palette Manager. This isn’t the only
- color matching method available; a custom search procedure, for example, may not have
- an inverse table. (See the section titled “Custom Search and Complement Procedures”
- for more information.) However, inverse tables are the default method for color
- matching.
-
- When using an inverse table, the table is indexed by concatenating together the
- high-order bits of the three desired color components; iTabRes tells how many bits of
- each component are significant. The format of an inverse table is shown below:
-
- TYPE
- ITabHandle = ^ITabPtr;
- ITabPtr = ^ITab;
- ITab = RECORD
- iTabSeed: LONGINT; {copy of color table seed}
- iTabRes: INTEGER; {resolution of table}
- iTTable: ARRAY[0..0] OF SignedByte {byte color }
- { table index values}
- END;
-
- The size of an index table in bytes is 2^3*iTabRes. The table below shows a sample
- index table:
-
- resolution RGB color inverse-table size
- index
- 4-bit red=$1234,
- green=$5678,
- blue=$9ABC $0159 2^12 = 4K bytes
-
- 5-bit red=$1234,
- green=$5678,
- blue=$9ABC $0953 2^15 = 32K bytes
-
- MakeITable only supports 3-bit, 4-bit, and 5-bit resolution. Five bits is the maximum
- possible resolution, since the indices into a 6-bit table would have to be 18 bits
- long, more than a full word.
-
- _______________________________________________________________________________
-
-
- æKY Using…the…Color…Manager
- æC »USING THE COLOR MANAGER ColorManager
- _______________________________________________________________________________
-
- In the simplest cases, use of the Color Manager is transparent when invoking the new
- Color QuickDraw routines. Using RGBForeColor and RGBBackColor, the program requests
- an RGB color for either the foreground or background. For instance, the following
- code requests an RGB color of red and sets it in the cGrafPort:
-
- myColor.red:=$FFFF;
- myColor.green:=0;
- myColor.blue:=0;
- RGBForeColor(myColor); {set pen red}
- FrameRect(myRect); {draw in red}
-
- Internally the Color Manager finds the best match to a color in TheGdevice’s current
- color table, and sets up the current cGrafPort to draw in this color. At this point,
- drawing operations can proceed using the selected colors.
-
- The Color Manager routines described in this chapter are designed to operate on a
- single gDevice. The Palette Manager can perform most of these operations across
- multiple gDevices. Since the Palette Manager provides more general and portable
- functionality, applications should use Palette Manager routines whenever possible.
-
- The SetEntries routine is used to change any part of or all of the entries in a
- device’s hardware Color Look-Up Table. The SaveEntries and RestoreEntries routines
- can make temporary changes to the color table under very specialized circumstances
- (such as a color selection dialog within an application). These routines aren’t
- needed under normal application circumstances.
-
- SaveEntries allows any combination of colorSpecs to be copied into a special colorTable.
- RestoreEntries replaces the table created by SaveEntries into the graphics device.
- Unlike SetEntries, these routines don’t perform invalidations of the device’s colorTable,
- so they avoid causing invalidations of cached data structures. When these routines
- are used, the application must take responsibility for rebuilding and restoring
- auxiliary structures as necessary.
-
- By convention, when using SetEntries or RestoreEntries, white should be located at
- color table position 0, and black should be stored in the last color table position
- available, whether it is 1, 3, 15, or 255. The Palette Manager also enforces this
- convention.
-
- For precise control over color, or for dedicated color table entries, the Color
- Manager routines maintain special information in device color tables. Using ProtectEntry
- and ReserveEntry, an entry may be protected, which prevents SetEntries from further
- changing the entry, or reserved, which makes the entry unavailable to be matched by
- RGBForeColor and RGBBackColor. Routines that change the device table (SetEntries,
- ProtectEntry, and ReserveEntry, but not RestoreEntries) will perform the appropriate
- invalidations of QuickDraw data structures. The application must then redraw where
- necessary.
-
- To inquire if a color exists in a color table, use RealColor. This tells whether an
- arbitrary color actually exists in the table for that gDevice.
-
- Color2Index returns the index in the current device’s colorTable that is the best
- match to the requested color. Index2Color performs the opposite function—it returns
- the RGB of a particular index value. These routines can be useful when making copies
- of the screen frame buffer. InvertColor finds the complement of the provided color.
- GetSubTable performs a group Color2Index on a colorTable.
-
- _______________________________________________________________________________
-
-
- æKY Color…Manager…Routines
- æC »COLOR MANAGER ROUTINES ColorManager
- _______________________________________________________________________________
-
- The routines used for color drawing are covered in the chapter “Color
- QuickDraw”. The Color Manager includes routines for color conversion, color table
- management, and error handling.
-
- _______________________________________________________________________________
-
- »Color Conversion
-
- FUNCTION Color2Index (rgb: RGBColor): LONGINT;
-
- The Color2Index routine finds the best available approximation to a given absolute
- color, using the list of search procedures in the current device record. It returns a
- longint, which is a pixel value padded with zeros in the high word. Since the colorSpec.value
- field is only a word, the result returned from Color2Index must be truncated to fit
- into a colorSpec. In pixMaps the
- .value is the low-order word of this index.
-
- Color2Index shouldn’t be called from a custom search procedure.
-
- PROCEDURE Index2Color (index: LONGINT; VAR rgb: RGBColor);
-
- The Index2Color routine finds the RGB color corresponding to a given color table
- index. The desired pixel value is passed and the corresponding RGB value is returned
- in RGB. The routine takes a longint, which should be a pixel value padded with zeros
- in the high word (normally the compiler does this automatically). Normally, the RGB
- from the current device color table corresponding to the index is returned as the
- RGBColor. Notice that this is not necessarily the same color that was originally
- requested via RGBForeColor, RGBBackColor, SetCPixel, or Color2Index. This RGB is read
- from the current gDevice color table.
-
- PROCEDURE InvertColor (VAR theColor: RGBColor);
-
- The InvertColor routine finds the complement of an absolute color, using the list of
- complement procedures in the current device record. The default complement procedure
- uses the 1’s complement of each component of the requested color.
-
- FUNCTION RealColor (color: RGBColor) : BOOLEAN;
-
- The RealColor routine tells whether a given absolute color actually exists in the
- current device’s color table. This decision is based on the current resolution of the
- inverse table. For example, if the current iTabRes is four, RealColor returns TRUE if
- there exists a color that exactly matches the top four bits of red, green, and blue.
-
- PROCEDURE GetSubTable (myColors: CTabHandle; iTabRes:INTEGER;
- targetTbl: CTabHandle);
-
- The GetSubTable routine takes a ColorTable pointed at by myColors, and maps each RGB
- value into its nearest available match for each target table. These best matches are
- returned in the colorSpec.value fields of myColors. The values returned are best
- matches to the RGBColor in targetTbl and the returned indices are indices into targetTbl.
- Best matches are calculated using Color2Index and all applicable rules apply. A
- temporary inverse table is built, and then discarded. ITabRes controls the resolution
- of the iTable that is built. If targetTbl is NIL, then the current device’s color
- table is used, and the
- device’s inverse table is used rather than building a new one. To provide a different
- resolution than the current inverse table, provide an explicit targetTbl parameter;
- don’t pass a NIL parameter.
-
- Warning: Depending on the requested resolution, building the inverse table
- can require large amounts of temporary space in the application
- heap: twice the size of the table itself, plus a fixed overhead
- for each inverse table resolution of 3–15K bytes.
-
- PROCEDURE MakeITable (colorTab: CTabHandle; inverseTab: ITabHandle;
- res: INTEGER);
-
- The MakeITable routine generates an inverse table based on the current contents of
- the color table pointed to by CTabHandle, with a resolution of res bits per channel.
- Reserved color table pixel values are not included in the resultant color table.
- MakeITable tests its input parameters and will return an error in QDError if the
- resolution is less than three or greater than five. Passing a NIL parameter to CTabHandle
- or ITabHandle substitutes an appropriate handle from the current gDevice, while
- passing 0 for res substitutes the current gDevice’s preferred table resolution. These
- defaults can be used in any combination with explicit values, or with NIL parameters.
-
- This routine allows maximum precision in matching colors, even if colors in the color
- table differ by less than the resolution of the inverse table. Five-bit inverse
- tables are not needed when drawing in normal QuickDraw modes. However, the new QuickDraw
- transfer modes (add, subtract, blend, etc.) may require a
- 5-bit inverse table for best results with certain color tables. MakeITable returns a
- QDError if the destination inverse table memory cannot be allocated. The 'mitq'
- resource governs how much memory is allocated for temporary internal structures; this
- resource type is for internal use only.
-
- Warning: Depending on the requested resolution, building the inverse table
- can require large amounts of temporary space in the application
- heap: twice the size of the table itself, plus a fixed overhead
- for each inverse table resolution of 3–15K bytes.
-
- _______________________________________________________________________________
-
- »Color Table Management
-
- FUNCTION GetCTSeed : LONGINT;
-
- The GetCTSeed function returns a unique seed value that can be used in the ctSeed
- field of a color table created by an application. This seed value guarantees that the
- color table will be recognized as distinct from the destination, and that color table
- translation will be performed properly. The return value will be greater than the
- value stored in minSeed.
-
- PROCEDURE ProtectEntry (index: INTEGER; protect: BOOLEAN);
-
- The ProtectEntry procedure protects or removes protection from an entry in the current
- device’s color table, depending on the value of the protect parameter. A protected
- entry can’t be changed by other clients. It returns a protection error if it attempts
- to protect an already protected entry. However, it can remove protection from any
- entry.
-
- PROCEDURE ReserveEntry (index: INTEGER; reserve: BOOLEAN);
-
- The ReserveEntry procedure reserves or dereserves an entry in the current color
- table, depending on the value of the reserve parameter. A reserved entry cannot be
- matched by another client’s search procedure, and will never be returned to another
- client by Color2Index or other routines that depend on it
- (such as RGBForeColor, RGBBackColor, SetCPixel, and so forth). You could use this
- routine to selectively protect a color for color table animation.
-
- ReserveEntry copies the low byte of gdID into the low byte of ColorSpec.value when
- reserving an entry, and leaves the high byte alone. It acts like a selective protection,
- and does not allow any changes if the current gdID is different than the one in the
- colorSpec.value field of the reserved entry. If a requested match is already reserved,
- ReserveEntry returns a protection error. Any entry can be dereserved.
-
- PROCEDURE SetEntries(start, count: INTEGER; aTable: CSpecArray);
-
- The SetEntries procedure sets a group of color table entries for the current gDevice,
- starting at a given position for the specified number of entries. The pointer aTable
- points into a cSpecArray, not into a color table. The colorSpec.value field of the
- entries must be in the logical range for the target card’s assigned pixel depth.
- Thus, with a 4-bit pixel size, the colorSpec.value fields should be in the range 1 to
- 15. With an 8-bit pixel size the range is 0 to 255. Note that all values are zero-based;
- for example, to set three entries, pass two in the count parameter.
-
- Note: Palette Manager routines should be used instead of the SetEntries
- routine for applications that will run in a multiscreen or
- multitasking environment.
-
- The SetEntries positional information works in logical space, rather than in the
- actual memory space used by the hardware. Requesting a change at position four in the
- color table may not modify color table entry four in the hardware, but it does correctly
- change the color on the screen for any pixels with a value of four in the video card.
- The SetEntries mode characterized by a start position and a length is called sequence
- mode. In this case, new colors are sequentially loaded into the hardware in the same
- order as the aTable, the clientID fields for changed entries are copied from the
- current device’s gdID field, and the colorSpec.value fields are ignored.
-
- The other SetEntries mode is called index mode. It allows the cSpecArray to specify
- where the data will be installed on an entry-by-entry basis. To use this mode, pass
- –1 for the start position, with a valid count and a pointer to the cSpecArray. Each
- entry is installed into the color table at the position specified by the colorSpec.value
- field of each entry in the cSpecArray. In the current device’s color table, all
- changed entries’ colorSpec.value fields are assigned the gdID value.
-
- When color table entries are changed, all cached fonts are invalidated, and the seed
- number is changed so that the next drawing operation will rebuild the inverse table.
- If any of the requested entries are protected or out of range, a protection error is
- returned, and nothing happens. If a requested entry is reserved, it can only be
- changed if the current gdID matches the low byte of the intended ColorSpec.value
- field.
-
- PROCEDURE SaveEntries (srcTable: CTabHandle; ResultTable: CTabHandle;
- VAR selection: ReqListRec);
-
- SaveEntries saves a selection of entries from srcTable into resultTable. The entries
- to be set are enumerated in the selection parameter, which uses the ReqListRec data
- structure shown below. (These values are offsets into colorTable, not the contents of
- the colorSpec.value field.)
-
- TYPE
- ReqListRec = RECORD
- reqLSize: INTEGER; {request list size –1}
- reqLData: ARRAY [0..0] of INTEGER {request list data}
- END;
-
- If an entry is not present in srcTable, then that position of the requestList is set
- to colReqErr, and that position of resultTable has random values returned. If one or
- more entries are not found, then an error code is posted to QDError; however, for
- every entry in selection which is not colReqErr, the values in resultTable are valid.
- Note that srcTable and selection are assumed to have the same number of entries.
-
- SaveEntries optionally allows NIL as its source color table parameter. If NIL is
- used, the current device’s color table is used as the source. The output of SaveEntries
- is the same as the input for RestoreEntries, except for the order.
-
- PROCEDURE RestoreEntries (srcTable:CTabHandle;DstTable:CTabHandle;
- VAR selection:ReqListRec);
-
- RestoreEntries sets a selection of entries from srcTable into dstTable, but doesn’t
- rebuild the inverse table. The dstTable entries to be set are enumerated in the
- selection parameter, which uses the ReqListRec data structure shown in the SetEntries
- routine description. (These values are offsets into the srcTable, not the contents of
- the colorSpec.value field.)
-
- If a request is beyond the end of the dstTable, that position of the requestList is
- set to colReqErr, and an error is returned. Note that srcTable and selection are
- assumed to have the same number of entries.
-
- If dstTbl is NIL, or points to the device color table, the current device’s color
- table is updated, and the hardware is updated to these new colors. The seed is not
- changed, so no invalidation occurs (this may cause RGBForeColor to act strangely).
- This routine ignores protection and reservation of color table entries.
-
- Generally, the Palette Manager is used to give an application its own set of colors;
- use of RestoreEntries should be limited to special-purpose applications. RestoreEntries
- allows you to change the colorTable without changing the ctSeed for the affected
- colorTable. You can execute the application code and then use RestoreEntries to put
- the original colors back in. However, in some cases things in the background may
- appear in the wrong colors, since they were never redrawn. To avoid this, the application
- must build its own new inverse table and redraw the background. If RestoreEntries
- were then used, the ctSeed would have to be explicitly changed to clean up correctly.
-
- _______________________________________________________________________________
-
- »Error Handling
-
- FUNCTION QDError: INTEGER;
-
- The QDError routine returns the error result from the last QuickDraw or Color Manager
- call. This routine is even more useful with 32-Bit QuickDraw. It is important that
- you check for errors after every QuickDraw call. For more information, see the
- 32-Bit QuickDraw documentation.
-
- _______________________________________________________________________________
-
-
- æKY Custom…Search…and…Complement…Functions
- æC »CUSTOM SEARCH AND COMPLEMENT FUNCTIONS ColorManager
- _______________________________________________________________________________
-
- The custom search function allows an application to override the inverse table matching
- code. The desired color is specified in the RGBColor field of a ColorSpec record and
- passed via a pointer on the stack; the procedure returns the corresponding pixel
- value in the ColorSpec.value field.
-
- A custom search routine can provide its own matching rules. For instance, you might
- want to map all levels of green to a single green on a monitor. To do this, you could
- write and install a custom search procedure that is passed the RGB under question by
- the Color Manager. It can then analyze the color, and if it decides to act on this
- color, it can return the index of the desired shade of green. Otherwise, it can pass
- the color back to the Color Manager for matching, using the normal inverse table
- routine.
-
- Many applications can share the same graphics device, each with its own custom search
- procedure. The procedures are chain elements in a linked list beginning in the
- gdSearchProc field of the gDevice port:
-
- TYPE
- SProcHndl = ^SProcPtr;
- SProcPtr = ^SProcRec;;
- SProcRec = RECORD
- nxtSrch: SProcHndl; {handle to next sProcRec}
- srchProc: ProcPtr {pointer to search procedure}
- END;
-
- Any number of search procedures can be installed in a linked list, each element of
- which will be called sequentially by the Color Manager, and given the chance to act
- or pass on the color. Since each device is a shared resource, a simple method (the
- gdID) is provided to identify the caller to the search procedures, as well as routines
- to add and delete custom procedures from the linked list.
-
- The interface is as follows:
-
- FUNCTION SearchProc (rgb: RGBColor; VAR position: LONGINT): BOOLEAN;
-
- When attempting to approximate a color, the Color Manager calls each search procedure
- in the list until the boolean value returns as TRUE. The index value of the closest
- match is returned by the position parameter. If no search procedure installed in the
- linked list returns TRUE, the Color Manager calls the default search procedure.
-
- The application can also supply a custom complement procedure to find the complement
- of a specified color. Complement procedures work the same as search procedures, and
- are kept in a list beginning in the gDevice port’s gdCompProc field.
-
- TYPE
- CProcHndl = ^CProcPtr;
- CProcPtr = ^CProcRec;
- CProcRec = RECORD
- nxtComp: CProcHandle; {pointer to next CProcRec}
- compProc: ProcPtr {pointer to complement procedure}
- END;
-
- The default complement procedure simply uses the 1’s complement of the RGB color
- components before looking them up in the inverse table. The interface is as follows:
-
- FUNCTION CompProc (VAR rgb: RGBColor) : BOOLEAN;
-
- _______________________________________________________________________________
-
- »Operations on Search and Complement Functions
-
- PROCEDURE AddSearch (searchProc: ProcPtr);
- PROCEDURE AddComp (compProc: ProcPtr);
-
- The AddSearch and AddComp routines add a procedure to the head of the current device
- record’s list of search or complement procedures. These routines allocate an SProcRec
- or CProcRec.
-
- PROCEDURE DelSearch (searchProc: ProcPtr);
- PROCEDURE DelComp (compProc: ProcPtr);
-
- The DelSearch and DelComp procedures remove a custom search or complement procedure
- from the current device record’s list of search or complement procedures. These
- routines dispose of the chain element, but do nothing to the procPtr.
-
- PROCEDURE SetClientID (id: INTEGER);
-
- The SetClientID procedure sets the gdID field in the current device record to identify
- this client program to its search and complement procedures.
-
- _______________________________________________________________________________
-
-
- æKY Summary…of…the…Color…Manager
- æC »SUMMARY OF THE COLOR MANAGER ColorManager
- _______________________________________________________________________________
-
- Constants
-
- CONST
- minSeed = 1023; {minimum seed value for ctSeed}
-
- _______________________________________________________________________________
-
- Data Types
-
- TYPE
- ITabHandle = ^ITabPtr;
- ITabPtr = ^ITab;
- ITab = RECORD
- iTabSeed: LONGINT; {copy of color table seed}
- iTabRes: INTEGER; {resolution of table}
- iTTable: ARRAY[0..0] OF SignedByte {byte color }
- { table index values}
- END;
-
- SProcHndl = ^SProcPtr;
- SProcPtr = ^SProcRec;;
- SProcRec = RECORD
- nxtSrch: SProcHndl; {handle to next sProcRec}
- srchProc: ProcPtr {pointer to search procedure}
- END;
-
- CProcHndl = ^CProcPtr;
- CProcPtr = ^CProcRec;
- CProcRec = RECORD
- nxtComp: CProcHandle; {pointer to next CProcRec}
- compProc: ProcPtr {pointer to complement procedure}
- END;
-
- ReqListRec = RECORD
- reqLSize: INTEGER; {request list size –1}
- reqLData: ARRAY [0..0] of INTEGER {request list data}
- END;
-
- _______________________________________________________________________________
-
- Routines
-
- Color Conversion
-
- FUNCTION Color2Index (VAR rgb: RGBColor): LONGINT;
- PROCEDURE Index2Color (index: LONGINT; VAR rgb: RGBColor);
- PROCEDURE InvertColor (VAR theColor: RGBColor);
- FUNCTION RealColor (color: RGBColor) : BOOLEAN;
- PROCEDURE GetSubTable (myColors: CTabHandle; iTabRes: INTEGER;
- targetTbl:CTabHandle);
- PROCEDURE MakeITable (colorTab: CTabHandle; inverseTab: ITabHandle;
- res: INTEGER);
-
- Color Table Management
-
- FUNCTION GetCTSeed: LONGINT;
- PROCEDURE ProtectEntry (index: INTEGER; protect: BOOLEAN);
- PROCEDURE ReserveEntry (index: INTEGER; reserve: BOOLEAN);
- PROCEDURE SetEntries (start, count: INTEGER; aTable: cSpecArray);
- PROCEDURE RestoreEntries (srcTable:CTabHandle;dstTable:CTabHandle;
- VAR selection:ReqListRec);
- PROCEDURE SaveEntries (srcTable:CTabHandle;resultTable:CTabHandle; VAR selection:ReqListRec)
-
- Operations on Search and Complement Functions
-
- PROCEDURE AddSearch (searchProc: ProcPtr);
- PROCEDURE AddComp (compProc: ProcPtr);
- PROCEDURE DelSearch (searchProc: ProcPtr);
- PROCEDURE DelComp (compProc: ProcPtr);
- PROCEDURE SetClientID (id: INTEGER);
-
- Error Handling
-
- FUNCTION QDError: INTEGER;
-
- _______________________________________________________________________________
-
- Assembly Language Information
-
- Constants
-
- minSeed EQU 1023 ;minimum ctSeed value
-
- ITab structure
-
- iTabSeed EQU $0 ;[long] ID of owning color table
- iTabRes EQU $4 ;[word] client ID
- iTTable EQU $6 ;table of indices starts here
- ;in this version, entries are BYTE
-
- SProcRec structure
-
- nxtSrch EQU $0 ;[pointer] link to next proc
- srchProc EQU $4 ;[pointer] pointer to routine
-
- CProcRec structure
-
- nxtComp EQU $0 ;[pointer] link to next proc
- compProc EQU $4 ;[pointer] pointer to routine
-
- Request list structure
-
- reqLSize EQU 0 ;[word] request list size –1
- reqLData EQU 2 ;[word] request list data
-
- Further Reference:
- _______________________________________________________________________________
- Color QuickDraw
- Graphics Devices
- Palette Manager
- Color Picker Package
- 32-Bit QuickDraw Documentation
-
- æKY ColorPickerPackage
- æC
- _______________________________________________________________________________
-
- COLOR PICKER PACKAGE
- _______________________________________________________________________________
-
- About…the…Color…Picker…Vol…VI…Chapter
- About…the…Color…Picker…Vol…VI…Package
- Color…Models
- The…RGB…Model
- The…CMYK…Model
- The…HLS…and…HSV…Models
- Color…Models…in…the…Dialog…Box
- Using…the…Color…Picker…Package…Vol…VI
- Presenting…the…Dialog…Box
- Conversion…Facilities…Vol…VI
- Color…Picker…Routines
- Displaying…the…Color…Picker…Dialog…Box
- Converting…Between…Color…Models
- Converting…Between…SmallFract…and…Fixed…Values
- Summary…of…the…Color…Picker…Package…Vol…VI
- Color…Picker…Package…Constants
- Color…Picker…Package…Data…Types
- Color…Picker…Package…Routines…Vol…VI
- Assembly…Language…Information…for…Color…Picker…Package
-
- About…The…ColorPickerPackage…Chapter
- The…Color…Picker…Package
- The…Color…Picker…Dialog…Box
- Color…Picker…Package…Routines
- Conversion…Facilities
- Summary…of…the…Color…Picker…Package
-
- _______________________________________________________________________________
-
-
-
- æKY About…the…Color…Picker…Chapter…Vol…VI
- æC »ABOUT THIS CHAPTER Color Picker Package
- _______________________________________________________________________________
-
- This chapter describes the Color Picker Package, a utility with which
- applications can offer users a standard dialog box for choosing a color. You
- should be familiar with the material in the Graphics Overview chapter in this
- volume, especially the discussion of direct and indexed video devices. Effective
- use of the Color Picker will also require familiarity with Color QuickDraw,
- described in Volume V of Inside Macintosh, and in this volume.
-
- This chapter supersedes the description of the Color Picker in Volume V.
-
- You need to read this chapter if your application uses the color system
- introduced with Color QuickDraw (rather than the 8-color system available with
- the original QuickDraw), and you need to solicit color choices from your users.
- If your application limits user selection to a specific list of colors, you may
- need to construct your own dialog box for color selection using Palette Manager
- routines, as the Color Picker allows the user to choose colors from the entire
- range available with Color QuickDraw’s 48-bit RGB values.
-
- _______________________________________________________________________________
-
- æKY About…the…Color…Picker…Package…Vol…VI
- æC »ABOUT THE COLOR PICKER PACKAGE Color Picker Package
- _______________________________________________________________________________
-
- The Color Picker Package provides you with a standard way of soliciting a color
- choice from the user. When an application calls the Color Picker’s GetColor
- function, the Color Picker presents its dialog box to the user, as shown in
- Figure 17-1.
-
- When the user is satisfied with a chosen color and clicks the OK button,
- GetColor returns that color to your application as an RGB value.
-
- ø 17.1 The Color Picker dialog box
-
- The Color Picker also has utility routines for converting between RGB values and
- several other color systems, and for converting between the integers Color
- QuickDraw uses for RGB colors and the SmallFract values the Color Picker uses
- with alternate color models.
-
- This chapter describes the color models the Color Picker works with, and how you
- set up and present the dialog box to users.
-
- _______________________________________________________________________________
-
- æKY Color…Models
- æC »COLOR MODELS Color Picker Package
- _______________________________________________________________________________
-
- Both QuickDraw and standard video monitors work with a red, green, blue (RGB)
- color model, but in graphic arts and design other color models, such as HLS
- (hue, lightness, saturation) or HSV (hue, saturation, value) are used, and in
- printing the CMYK (cyan, magenta, yellow, and black) model predominates. Great
- books have been written about color; this section presents a quick survey of the
- models with which the Color Picker works.
-
- _______________________________________________________________________________
-
- æKY The…RGB…Model
- æC »The RGB Model Color Picker Package
- _______________________________________________________________________________
-
- In the RGB model, the three colors are additive. The more of each color you add
- the closer the resulting color is to white. This is the way light-produced
- colors work; turning on the red, green, and blue phosphors of a television
- screen produces white, as does shining lights of red, green, and blue upon a
- stage.
-
- The QuickDraw data structure for an RGBColor record is
-
- RGBColor = RECORD
- red: Integer; {red component}
- green: Integer; {green component}
- blue: Integer {blue component}
- END;
-
- The frontispiece of Volume V of Inside Macintosh shows a color cube that
- represents the values possible in an RGB system. Figure 17-2 is a
- black-and-white representation of that cube.
-
-
-
- ø 17.2 The RGB Color Cube
-
- Starting at one corner, with zero values for each color, is black. Increasing
- any one of the values produces shades of that color, increasing its saturation.
- Increasing all three values equally generates a diagonal line across the cube
- toward full value (65,535) for each, which is white. Values on that diagonal are
- shades of gray; values off the line in any direction are colors. For example,
- pink in the RGB model would be full red with some equal amount of green and
- blue, in effect moving from the black corner of the color cube up along the edge
- to full red, then traversing a diagonal across the top face from red toward
- white.
-
-
- ø 17.3 Getting to pink
-
- _______________________________________________________________________________
-
- æKY The…CMYK…Model
- æC »The CMYK Model Color Picker Package
- _______________________________________________________________________________
-
- In the CMYK model, which is used by the print world, the three colors and black
- are subtractive: increasing values moves the result closer to black. This is
- intuitive for printing, which is usually done on white paper—to get white, don’t
- print anything. In theory, black could be achieved by mixing full values of
- cyan, magenta, and yellow, but purity in chemicals is more problematic than with
- light, and four-color print processes use black as well. The Color Picker’s
- CMYColor data structure defines only the three colors. It uses SmallFract
- values, which are the fractional part of Fixed values, as described in Color
- Picker Conversion Facilities.
-
- CMYColor = RECORD
- cyan: SmallFract;
- magenta: SmallFract;
- yellow: SmallFract
- END;
-
- Note that cyan, magenta, and yellow are complements of red, green, and blue.
-
- ø 17.4 CMY on the color cube
-
- _______________________________________________________________________________
-
- æKY The…HLS…and…HSV…Models
- æC »The HLS and HSV Models Color Picker Package
- _______________________________________________________________________________
-
- The components of the HLS and HSV models are not three diverse colors, as in RGB
- and CMY. The HLS and HSV models separate color, or hue, from brightness and
- saturation.
-
- Brightness is a measure of how much black is in a color, saturation is a measure
- of how much white it contains. Hue is indicated by an arbitrary assignment of
- numbers to colors. The amount of that hue is indicated by a saturation value,
- and the brightness of the color is a third value. The best representation for
- such a system is an inverted cone, in which hues vary around the perimeter,
- where they are most highly saturated, and brightness increases from the tip of
- the cone to the disk. The gray line from black to white begins at the bottom-tip
- and runs up through the cone to the center of the disk.
-
- ø 17.5 The HLS/HSV color cone
-
- This is the model portrayed in the Color Picker’s dialog box. The disk is shown
- full face, the hues are at their most saturated around the rim, and the
- brightness line down the cone is controlled by the scroll bar.
-
- In the Color Picker’s color wheel the value for pure red is 0, pure green is
- 21,845, and pure blue is 43,690. The amount of black is set by the value for
- brightness (meaning lightness in HLS, value in HSV), and the amount of color in
- the mix is set by saturation. Pink in the HLS or HSV system would be obtained by
- setting hue to red, saturation to some amount less than full, and brightness to
- full.
-
- The HLS and HSV systems are sufficiently similar that the Color Picker can treat
- them as one by a simple expedient: the HLS model is treated by the Picker as if
- it were ordered HSL; this puts hue and saturation in the same relative positions
- in the data structures of both models.
-
- HSVColor = RECORD
- hue: SmallFract; {fraction of circle, red at 0}
- saturation: SmallFract; {0-1, 0 is gray, 1 is pure color}
- value: SmallFract {0-1, 0 is black, 1 is max intensity}
- END;
-
- HSLColor = RECORD
- hue: SmallFract; {fraction of circle, red at 0}
- saturation: SmallFract; {0-1, 0 is gray, 1 is pure color}
- lightness: SmallFract {0-1, 0 is black, 1 is white}
- END;
- _______________________________________________________________________________
-
- æKY Color…Models…in…the…Dialog…Box
- æC »Color Models in the Dialog Box Color Picker Package
- _______________________________________________________________________________
-
- The controls in the dialog box are designed for use in the HSL or HSV models:
- hue is chosen by moving the cursor around the color wheel, saturation by moving
- in or out from the center, and brightness (value or lightness) is specified by
- the scroll bar at the right. The way RGB values vary in response to the dialog
- controls is not intuitive, but it can be instructive on how the models relate.
-
- The dialog box cannot exactly match the print world’s additive effect, and it
- does not offer CMYK controls, but routines for converting between RGB and CMY
- (cyan, magenta, yellow, without a black component) are included in the Color
- Picker Package.
-
- _______________________________________________________________________________
-
- æKY Using…the…Color…Picker…Package…Vol…VI
- æC »USING THE COLOR PICKER PACKAGE Color Picker Package
- _______________________________________________________________________________
-
- Most developers will only use the Color Picker Package to display the Color
- Picker’s dialog box. A few developers may need to use the color model and
- SmallFract conversion routines.
-
- _______________________________________________________________________________
-
- æKY Presenting…the…Dialog…Box
- æC »Presenting the Dialog Box Color Picker Package
- _______________________________________________________________________________
-
- Your program can present a user with the Color Picker dialog box, shown in
- Figure 1, by calling the Color Picker’s GetColor function.
-
- When called by an application, the Color Picker displays the dialog box,
- including prompt text, which appears in the upper-left corner, and the initial
- color, which appears in the lower of the two rectangles below the prompt. The
- color being picked, in the upper rectangle, ranges over the entire color space
- in response to the controls in the rest of the dialog box. Your application can
- supply the prompt text, an initial color, the location of the upper-left corner
- of the dialog box window, and whether it should appear on the main or deepest
- screen.
-
- The two groups of numeric fields (Hue/Saturation/Brightness and Red/Green/Blue)
- show the parameters of the color being picked in the two color systems. The user
- may increase or decrease the values using the arrow controls or enter values
- directly into any of the six fields.
-
- The range for all of the component values is 0 to 65,535. Larger values are
- clipped to 65,535 after the user exits the field. When the user is increasing or
- decreasing the hue using the arrow controls, 0 wraps around to 65,535, so the
- user can circumnavigate the wheel with arrow controls just as with the cursor.
- The hue value for pure red is 0; pure green is 21,845; pure blue is 43,690.
-
- The user may select a single RGB value from Color QuickDraw’s entire range of
- 248 color values.
-
- On black-and-white hardware (or in less than 4-bit mode), the display appears in
- black and white; the Color Picker returns the RGB value selected, but does not
- call any color routines in the course of responding to user actions.
-
- On devices with a variable CLUT, the Color Picker temporarily borrows a color
- table entry to display the exact color in the rectangle that shows the color
- currently being picked. (As a result, when your application subsequently
- displays the user’s chosen color, if you let the Color Manager approximate the
- user’s value the result will probably differ somewhat from the one picked.) The
- Color Picker restores the color environment when it is done.
-
- _______________________________________________________________________________
-
- æKY Conversion…Facilities…Vol…VI
- æC »Conversion Facilities Color Picker Package
- _______________________________________________________________________________
-
- In addition to the GetColor function that puts up the Color Picker dialog box,
- the Color Picker provides six procedures for converting between RGB and the CMY,
- HLS, and HSV color systems; and two functions that convert between SmallFract
- and fixed numbers. Most developers will use only the GetColor function.
-
- The CMY, HSL, and HSV structures are defined by ColorPicker with SmallFract
- values rather than INTEGER values (as used in RGBColor). A SmallFract value is
- the fractional part of a Fixed number, which is the low-order word. The Integer
- values in RGBColor are actually used as unsigned integer-sized values; by using
- SmallFract values, the ColorPicker avoids sign extension problems in the
- conversion math. The Color Picker provides two functions for converting between
- SmallFract and fixed numbers. Most developers will not need to use these
- facilities.
-
- _______________________________________________________________________________
-
- æKY Color…Picker…Routines
- æC »COLOR PICKER ROUTINES Color Picker Package
- _______________________________________________________________________________
-
- The following cards describe the Color Picker routines.
- _______________________________________________________________________________
-
- æKY Displaying…the…Color…Picker…Dialog…Box
- æC »Displaying the Color Picker Dialog Box Color Picker Package
- _______________________________________________________________________________
-
- FUNCTION GetColor (where: Point; prompt: Str255; inColor: RGBColor; VAR
-
- outColor: RGBColor) : BOOLEAN;
-
- The GetColor function displays the Color Picker dialog box on the screen, with
- its upper-left corner located at the point you designate with the where
- parameter. The Color Picker Package will display the dialog box and accept color
- selection on any screen, not just the main screen. If where = (0,0), the dialog
- box is positioned neatly on the main screen—centered horizontally and with
- one-third of the empty space above the box and two-thirds below, whatever the
- screen size. If an application supplies a where parameter of -1,-1, the Color
- Picker will center the dialog box on what the Color Picker determines to be the
- best screen, maximizing for depth and color.
-
- The prompt string is displayed in the upper-left corner of the dialog box. The
- inColor parameter is the starting color, which the user may want for comparison;
- it is displayed immediately below the current output color (the one the user is
- picking). The OutColor parameter is set to the last color value the user picks,
- if and only if the user clicks OK. On entry, it is treated as undefined, so the
- output color sample originally matches the input. Although the color being
- picked may vary widely, the input color sample remains fixed, and clicking in
- the input sample resets the output color sample to match it.
-
- GetColor returns TRUE if the user exits by clicking the OK button or FALSE if
- the user cancels.
-
- _______________________________________________________________________________
-
- æKY Converting…Between…Color…Models
- æC »Converting Between Color Models Color Picker Package
- _______________________________________________________________________________
-
- These six routines offer conversions between RGB on the one hand and CMY, HSV,
- or HSL on the other.
-
- PROCEDURE CMY2RGB (cColor: CMYColor; VAR rColor: RGBColor);
-
- The CMY2RGB procedure converts a CMYColor record to an RGBColor record.
-
- PROCEDURE HSL2RGB (hColor: HSLColor; VAR rColor: RGBColor);
-
- The HSL2RGB procedure converts an HSLColor record to an RGBcolor record.
-
- PROCEDURE HSV2RGB (hColor: HSVColor; VAR rColor: RGBColor);
-
- The HSV2RGB procedure converts an HSVColor record to an RGBColor record.
-
- PROCEDURE RGB2CMY (rColor: RGBColor; VAR cColor: CMYColor);
-
- The RGB2CMY procedure converts an RGBColor record to a CMYColor record.
-
- PROCEDURE RGB2HSL (rColor: RGBColor; VAR hColor: HSLColor);
-
- The RGB2HSL procedure converts an RGBColor record to an HSLColor record.
-
- PROCEDURE RGB2HSV (rColor: RGBColor; VAR hColor: HSVColor);
-
- The RGB2HSV procedure converts an RGBColor record to an HSVColor record.
-
- _______________________________________________________________________________
-
- æKY Converting…Between…SmallFract…and…Fixed…Values
- æC »Converting Between SmallFract and Fixed Values Color Picker Package
- _______________________________________________________________________________
-
- A SmallFract value can represent a value between 0 and 65,535. They can be
- assigned directly to and from Integers.
-
- FUNCTION SmallFract2Fix(s: SmallFract): Fixed;
-
- The SmallFract2Fix function converts a SmallFract value to a fixed integer.
-
- FUNCTION Fix2SmallFract(f: Fixed): SmallFract;
-
- The Fix2SmallFract function converts a fixed integer to a SmallFract value.
- _______________________________________________________________________________
-
- æKY Summary…of…the…Color…Picker…Package…Vol…VI
- æC »SUMMARY OF THE COLOR PICKER PACKAGE Color Picker Package
- _______________________________________________________________________________
-
- The following cards summarize the constants, data types, and routines for the
- Color Picker Package.
- _______________________________________________________________________________
-
- æKY Color…Picker…Package…Constants
- æC »Constants Color Picker Package
- _______________________________________________________________________________
-
- CONST
-
- MaxSmallFract = $0000FFFF; {maximum SmallFract value, as LONGINT}
- _______________________________________________________________________________
-
- æKY Color…Picker…Package…Data…Types
- æC »Data Types Color Picker Package
- _______________________________________________________________________________
-
- TYPE
- SmallFract = INTEGER; {unsigned fraction between 0 and 1}
- HSVColor = RECORD
- hue: SmallFract; {fraction of circle, red at 0}
- saturation: SmallFract; {0-1, 0 is gray, 1 is pure color}
- value: SmallFract {0-1, 0 is black, 1 is max intensity}
- END;
-
- HSLColor = RECORD
- hue: SmallFract; {fraction of circle, red at 0}
- saturation: SmallFract; {0-1, 0 is gray, 1 is pure color}
- lightness: SmallFract {0-1, 0 is black, 1 is white}
- END;
-
- CMYColor = RECORD {CMY and RGB are complements}
- cyan: SmallFract;
- magenta: SmallFract;
- yellow: SmallFract
- END;
- _______________________________________________________________________________
-
- æKY Color…Picker…Package…Routines…Vol…VI
- æC »Routines Color Picker Package
- _______________________________________________________________________________
-
- Displaying the Dialog Box
-
- FUNCTION GetColor (where: Point; prompt: Str255; inColor: RGBColor; VAR
- outColor: RGBColor) : BOOLEAN;
-
- Converting Between Color Models
-
- PROCEDURE CMY2RGB (cColor: CMYColor; VAR rColor: RGBColor);
- PROCEDURE HSL2RGB (hColor: HSLColor; VAR rColor: RGBColor);
- PROCEDURE HSV2RGB (hColor: HSVColor; VAR rColor: RGBColor);
- PROCEDURE RGB2CMY (rColor: RGBColor; VAR cColor: CMYColor);
- PROCEDURE RGB2HSL (rColor: RGBColor; VAR hColor: HSLColor);
- PROCEDURE RGB2HSV (rColor: RGBColor; VAR hColor: HSVColor);
-
- Converting Between SmallFract and Fixed Values
-
- FUNCTION SmallFract2Fix (s: SmallFract): Fixed;
- FUNCTION Fix2SmallFract (f: Fixed): SmallFract;
- _______________________________________________________________________________
-
- æKY Assembly…Language…Information…for…Color…Picker…Package
- æC »Assembly Language Information Color Picker Package
- _______________________________________________________________________________
-
- Constants
-
- Fix2SmallFract .EQU 1 ; selector for Fix2SmallFract
- SmallFract2Fix .EQU 2 ; selector for mallFract2Fix
- CMY2RGB .EQU 3 ; selector for CMY2RGB
- RGB2CMY .EQU 4 ; selector for RGB2CMY
- HSL2RGB .EQU 5 ; selector for HSL2RGB
- RGB2HSL .EQU 6 ; selector for RGB2HSL
- HSV2RGB .EQU 7 ; selector for HSV2RGB
- RGB2HSV .EQU 8 ; selector for RGB2HSV
- GetColor .EQU 9 ; selector for GetColor
-
- Macro
- _Pack12
- _______________________________________________________________________________
-
-
-
- æKY About…The…ColorPickerPackage…Chapter
- æC »ABOUT THIS CHAPTER ColorPickerPackage
- _______________________________________________________________________________
-
- Warning: This chapter has not been updated to reflect changes and improvements
- that are available on systems using 32-Bit QuickDraw. For further
- information on 32-Bit QuickDraw, please refer to the 32-Bit QuickDraw
- documentation (available on “Phil & Dave’s Excellent CD: The Release
- Version).
-
- This chapter describes the Color Picker, a package that allows applications to present
- users with a standard interface for color selection. You should be familiar with
- color on the Macintosh and graphic devices, as discussed in the Color QuickDraw and
- Graphic Devices chapters.
- _______________________________________________________________________________
-
-
- æKY The…Color…Picker…Package
- æC »THE COLOR PICKER PACKAGE ColorPickerPackage
- _______________________________________________________________________________
-
- The Color Picker Package is a tool that applications can use to present a standard
- user interface for color selection. It also provides routines for converting color
- values between several different color systems. The Color Picker Package does not
- alter the Color Look-Up Table (CLUT), if any, associated with the current graphics
- device.
-
- Once the user chooses a color, Color Picker returns it to the application, in the
- form of an RGBColor value, leaving the graphics device in its original state. The
- application can do what it likes with the color selection, with as much or as little
- attention to the available graphics hardware as it deems appropriate. On black and
- white hardware (or in less than 4-bit mode), the display is in black and white; Color
- Picker returns the value selected, but does not call any color routines.
-
- On direct device hardware the exact color can be used without extra effort, while on
- fixed CLUT hardware it can only be approximated. On most hardware, such as Apple’s
- TFB graphics card, which has a variable CLUT, the application decides how faithfully
- to reproduce the color, because it can replace an entry in the device’s CLUT to show
- it exactly, or treat the table as fixed and approximate the color. Color Picker
- itself takes advantage of the hardware on such devices, displaying the exact color by
- borrowing a color table entry. As result, applications that are content to approximate
- the color will show users colors that differ somewhat from the ones picked.
-
- _______________________________________________________________________________
-
-
- æKY The…Color…Picker…Dialog…Box
- æC »THE COLOR PICKER DIALOG BOX ColorPickerPackage
- _______________________________________________________________________________
-
- Developers can present the Color Picker dialog box, shown in Figures 1 & 2
- (This illustration is in color in Figure 1 if you are using a color monitor in color
- mode.), to a user by means of the Color Picker routine, described later in this
- chapter.
-
- •••Refer to Figure 1.•••
-
- Figure 1–Color Picker Dialog Box (Color Version)
-
- •••Refer to Figure 2.•••
-
- Figure 2–Color Picker Dialog Box (B/W Version)
-
- When called by an application, the Color Picker supplies the prompt text, which
- appears in the upper-left corner, and the initial color, which appears in the bottom
- of the two rectangles below the prompt. The color being picked, in the upper rectangle,
- ranges rapidly over the entire color space, in response to the controls in the rest
- of the dialog. The calling application also supplies the location of the top-left
- corner of the dialog window.
-
- The user is allowed to select a single color, from the entire range the hardware can
- produce. The wheel allows users to select a given hue and saturation simultaneously.
- The center of the wheel displays zero saturation
- (no hue mixed in); the outer boundary is maximum saturation (no gray mixed in);
- colors on the edge of the wheel are pure hues. The scroll bar at right controls the
- brightness (value) of the wheel.
-
- The two groups of text fields (Hue/Saturation/Brightness and Red/Green/Blue) show the
- parameters of the color being picked in two independent color systems. Brightness
- represents value in the HSV model.
-
- The HSV values are the primary color system, which correspond to the controls in the
- dialog box. The RGB values are the alternate color system, and the way they vary in
- response to the dialog controls is not intuitive. Only users who understand both
- color systems will understand how the RGB values vary in relation to the rest of the
- dialog. (See the Color Quickdraw chapter for more information.) The alternate color
- system is intended to make life easier for users accustomed to something other than
- the HSV model.
-
- The range for all of the component values is 0 to 65,535. Larger values are clipped
- to the maximum after the user exits the field. When incrementing or decrementing the
- hue via the arrow controls, 0 wraps around to 65,535, and vice versa, so the user can
- circumnavigate the wheel unimpeded. The hue value for red is 0; green is 21,845;
- blue is 43,690.
-
- _______________________________________________________________________________
-
-
- æKY Color…Picker…Package…Routines
- æC »COLOR PICKER PACKAGE ROUTINES ColorPickerPackage
- _______________________________________________________________________________
-
- FUNCTION GetColor(where: Point; prompt: Str255; inColor: RGBColor;
- VAR outColor: RGBColor) : BOOLEAN;
-
- GetColor displays the Color Picker dialog box on the screen, with its top-left corner
- located at where. (The where Point should be on the main gDevice.) If where = (0,0),
- the dialog box is positioned neatly on the screen, centered horizontally, and with
- one third of the empty space above the box, two thirds below, whatever the screen
- size.
-
- The prompt string is displayed in the upper-left corner of the dialog box. InColor
- is the starting color, which the user may want for comparison, and is displayed
- immediately below the current output color (the one the user is picking). OutColor
- is set to the last color value the user picked, if and only if the user clicks OK.
- On entry, it is treated as undefined, so the output color sample originally matches
- the input. While the color being picked may vary widely, the input color sample
- remains fixed, and clicking in the input sample resets the output color sample to
- match it.
-
- GetColor returns TRUE if the user exits via the OK button, or FALSE if the user
- cancels.
-
- Assembly-language note: the trap macro for the Color Picker Package is
- _Pack12. The routine selectors are as follows:
-
- Fix2SmallFract .EQU 1
- SmallFract2Fix .EQU 2
- CMY2RGB .EQU 3
- RGB2CMY .EQU 4
- HSL2RGB .EQU 5
- RGB2HSL .EQU 6
- HSV2RGB .EQU 7
- RGB2HSV .EQU 8
- GetColor .EQU 9
-
- _______________________________________________________________________________
-
-
- æKY Conversion…Facilities
- æC »CONVERSION FACILITIES ColorPickerPackage
- _______________________________________________________________________________
-
- The Color Picker provides six procedures for converting color values between CMY and
- RGB, and between HSL or HSV and RGB. Most developers will not need to use these
- routines.
-
- PROCEDURE CMY2RGB (cColor: CMYColor; VAR rColor: RGBColor);
- PROCEDURE RGB2CMY (rColor: RGBColor; VAR cColor: CMYColor);
- PROCEDURE HSL2RGB (hColor: HSLColor; VAR rColor: RGBColor);
- PROCEDURE RGB2HSL (rColor: RGBColor; VAR hColor: HSLColor);
- PROCEDURE HSV2RGB (hColor: HSVColor; VAR rColor: RGBColor);
- PROCEDURE RGB2HSV (rColor: RGBColor; VAR hColor: HSVColor);
-
- For developmental simplicity in switching between the HLS and HSV models, HLS is
- reordered into HSL. Thus both models start with hue and saturation values; value/lightness/brightness
- is last.
-
- The CMY, HSL, and HSV structures are defined by ColorPicker with SmallFract values
- rather than INTEGER values (as in RGBColor). A SmallFract value is the fractional
- part of a Fixed number, which is the low-order word. The INTEGER values in RGBColor
- are actually used as unsigned integer-sized values; by using SmallFracts, ColorPicker
- avoids sign extension problems in the conversion math.
-
- The Color Picker provides two functions for converting between SmallFract and Fixed
- numbers. Most developers will not need to use these facilities.
-
- FUNCTION Fix2SmallFract(f: Fixed): SmallFract;
- FUNCTION SmallFract2Fix(s: SmallFract): Fixed;
-
- A SmallFract can represent a value between 0 and 65,535. They can be assigned
- directly to and from INTEGERs.
-
- _______________________________________________________________________________
-
-
- æKY Summary…of…the…Color…Picker…Package
- æC »SUMMARY OF THE COLOR PICKER PACKAGE ColorPickerPackage
- _______________________________________________________________________________
-
- Constants
-
- CONST
- MaxSmallFract = $0000FFFF; {maximum SmallFract value, as LONGINT}
-
- _______________________________________________________________________________
-
- Data Types
-
- TYPE
- SmallFract = INTEGER; {unsigned fraction between 0 and 1}
-
- HSVColor = RECORD
- hue: SmallFract; {fraction of circle, red at 0}
- saturation: SmallFract; {0-1, 0 is gray, 1 is pure color}
- value: SmallFract; {0-1, 0 is black, 1 is max intensity}
- END;
-
- HSLColor = RECORD
- hue: SmallFract; {fraction of circle, red at 0}
- saturation: SmallFract; {0-1, 0 is gray, 1 is pure color}
- lightness: SmallFract; {0-1, 0 is black, 1 is white}
- END;
-
- CMYColor = RECORD {CMY and RGB are complements}
- cyan: SmallFract;
- magenta: SmallFract;
- yellow: SmallFract;
- END;
-
- _______________________________________________________________________________
-
- Routines
-
- FUNCTION GetColor(where: Point; prompt: Str255; inColor: RGBColor;
- VAR outColor: RGBColor): BOOLEAN;
-
- Conversion Functions
-
- FUNCTION Fix2SmallFract(f: Fixed): SmallFract;
- FUNCTION SmallFract2Fix(s: SmallFract): Fixed;
-
- Color Conversion Procedures
-
- PROCEDURE CMY2RGB(cColor: CMYColor; VAR rColor: RGBColor);
- PROCEDURE RGB2CMY(rColor: RGBColor; VAR cColor: CMYColor);
- PROCEDURE HSL2RGB(hColor: HSLColor; VAR rColor: RGBColor);
- PROCEDURE RGB2HSL(rColor: RGBColor; VAR hColor: HSLColor);
- PROCEDURE HSV2RGB(hColor: HSVColor; VAR rColor: RGBColor);
- PROCEDURE RGB2HSV(rColor: RGBColor; VAR hColor: HSVColor);
-
- _______________________________________________________________________________
-
- Assembly-Language Information
-
- Constants
-
- Fix2SmallFract .EQU 1
- SmallFract2Fix .EQU 2
- CMY2RGB .EQU 3
- RGB2CMY .EQU 4
- HSL2RGB .EQU 5
- RGB2HSL .EQU 6
- HSV2RGB .EQU 7
- RGB2HSV .EQU 8
- GetColor .EQU 9
-
- Macro
-
- _PACK12
-
- Further Reference:
- _______________________________________________________________________________
- Color QuickDraw
- Graphics Devices
- 32-Bit QuickDraw Documentation
-
- æKY Color QuickDraw
- æC
- _______________________________________________________________________________
-
- COLOR QUICKDRAW
- _______________________________________________________________________________
-
- About…The…Color…Quickdraw…Vol…VI…Chapter
- About…Color…Quickdraw…Vol…VI
- Direct…Colors
- PixMap…Record…Extensions
- Direct…Pixel…Examples
- PICT…Extensions
- Well-Behaved…Graphics…Applications
- Using…Color…Quickdraw…Vol…VI
- Copying…PixMap…Records
- Dithering
- Resizing…Images
- Luminance…Mapping
- Image…Resolution
- Importing…PixMap…Records
- Exporting…PixMap…Records
- Converting…a…Bitmap…to…a…Region
- Checking…that…QuickDraw…is…Done
- New…Color…Quickdraw…Routines
- New…QuickDraw…Result…Codes
- Creating…an…Extended…PICT2…Picture
- From…Bitmap…to…Region
- Drawing…Completion
- Reporting…Data…Structure…Changes
- The…Extended…PICT2…Format
- Sample…Extended…PICT2…File
- PICT2…Opcode…Types
- Extended…PICT2…Opcodes
- Summary…of…Color…Quickdraw…Vol…VI…Changes
- Color…Quickdraw…Constants
- Color…Quickdraw…Data…Types
- Color…Quickdraw…Vol…VI…Routines
- Color…Quickdraw…Result…Codes
-
- About…The…ColorQuickDraw…Chapter
- Color…Representation
- Using…Color…on…the…Macintosh…II
- About…Color…QuickDraw
- The…Color…Graphics…Port
- The…Color…Cursor
- Color…Icons
- Using…Color…QuickDraw
- Color…QuickDraw…Routines
- Color…QuickDraw…Resource…Formats
- Using…Text…with…QuickDraw
- Color…Picture…Format
- PICT…Opcodes
- Summary…of…Color…QuickDraw
- _______________________________________________________________________________
-
-
-
- æKY About…The…Color…Quickdraw…Vol…VI…Chapter
- æC »ABOUT THIS CHAPTER Color QuickDraw
- _______________________________________________________________________________
-
- This chapter describes extensions to Color QuickDraw. You should be familiar
- with the Graphics Overview in this volume, and with the Color QuickDraw
- description in Inside Macintosh, Volume V. Developers of graphics cards and
- drivers should also be familiar with the Slot Manager, Graphics Devices Manager,
- and the Control Panel as described in both Inside Macintosh and and Developing
- Cards and Drivers for the Macintosh Family, second edition.
-
- This chapter describes extensions to the color facilities of Color QuickDraw,
- and other new features, notably luminance mapping techniques and routines by
- which existing applications can signal QuickDraw that a data structure has been
- modified directly, rather than by use of QuickDraw routines.
-
- If you use offscreen graphics to prepare images before copying them to the
- screen, read the Graphics Devices Manager chapter in this volume for a
- description of new routines that considerably reduce the complexity of that
- task.
- _______________________________________________________________________________
-
- æKY About…Color…Quickdraw…Vol…VI
- æC »ABOUT COLOR QUICKDRAW Color QuickDraw
- _______________________________________________________________________________
-
- Color QuickDraw now supports images that use direct, as well as indexed,
- specification of colors.
-
- Although an application specifies a color in terms of RGB space, the actual
- value Color QuickDraw sends to the graphics card frame buffer (video RAM) is an
- index value, which is used as input to the CLUT. An 8-bit index can specify 256
- different entries (2 to the 8th power). On CLUT devices, the relationship
- between the index value and the color generated depends on what colors are
- currently stored where in the table.
-
- At the cost of larger RAM requirements and, in some situations, slower
- performance, direct color specification eliminates the need for table look-ups
- and color searching algorithms, and lets your application directly specify over
- 16 million colors. (For a comparison of the differences between indexed and
- direct colors, see the Graphics Overview chapter.)
-
- In addition to direct color, Color QuickDraw now also provides
-
- • support for a true gray-scale display, providing better image fidelity on
- gray-scale devices
-
- • a routine that converts a BitMap record into a region, which means you
- can, in effect, use region-manipulating routines on BitMap records
-
- • four routines that enable you to signal Color QuickDraw when your
- application directly modifies a CLUT, PixPat, GrafPort, or GDevice data
- structure. (Direct modification is still discouraged.)
-
- • a routine that creates and retrieves pictures with variable dots per inch
- resolution
- _______________________________________________________________________________
-
- æKY Direct…Colors
- æC »DIRECT COLORS Color QuickDraw
- _______________________________________________________________________________
-
- Color QuickDraw now supports pixmaps with direct color specification as well as
- the indexed method supported by the original release of Color QuickDraw. Since
- QuickDraw has always striven to be device-independent, many applications need
- make no changes. If your application specifies RGB colors, the system determines
- the best colors for indexed devices and passes your RGB color to direct devices.
-
- Changes to the Color QuickDraw interface affect only these two
- color-specification data structures:
-
- • the PixMap data structure that describes an image
-
- • the PICT2 format in which images and graphics drawing operations are
- stored
-
- Extensions to these two structures are described next.
- _______________________________________________________________________________
-
- æKY PixMap…Record…Extensions
- æC »PixMap Record Extensions Color QuickDraw
- _______________________________________________________________________________
-
- Color QuickDraw supports two new pixel formats, corresponding to 16-bit and
- 32-bit pixel depths. In both cases, the pixel’s displayed color is specified by
- the pixel value; the pixel value is not an index into a CLUT.
-
- Note that the format of a PixMap record is not changed from that introduced with
- the Macintosh II, but six PixMap fields can have new values. The PixMap data
- structure is shown here, only the fields that can have new values are discussed.
- See the Color QuickDraw chapter in Volume V for a complete PixMap description.
-
- PixMap = RECORD
- baseAddr: Ptr; {pointer to PixMap data}
- rowBytes: Integer; {offset to next row}
- bounds: Rect; {boundary rectangle}
- pmVersion: Integer; {Color QuickDraw flags}
- packType: Integer; {packing format}
- packSize: Longint; {size of data in packed state}
- hRes: Fixed; {horizontal resolution}
- vRes: Fixed; {vertical resolution}
- pixelType: Integer; {format of pixel image}
- pixelSize: Integer; {physical bits per pixel}
- cmpCount: Integer; {logical components per pixel}
- cmpSize: Integer; {logical bits per component}
- planeBytes: Longint; {offset to next plane}
- pmTable: CTabHandle; {absolute colors for this image}
- pmReserved: Longint {reserved for future expansion}
- END;
-
- Direct fields
-
- rowBytes: The restriction that rowbytes be less than $2000 has been relaxed:
- rowbytes must be less than $4000. RowBytes must be even, and for best
- performance it should be a multiple of 4.
-
- pmVersion: Normally 0. If pmVersion is 4, Color QuickDraw treats the pixmap’s
- baseAddr as being 32-bit clean. This flag can be set by a new Graphics Devices
- Manager routine, SetPMVersion. Most applications never need to set this field;
- it is for low-level driver support.
-
- pixelType: Direct pixel values are specified by a pixelType field value of
- RGBDirect, or 16. In a PixMap record of the gDevice record for a direct device,
- the pixelType field will be set to the constant RGBDirect when the screen depth
- is set.
-
- pixelSize: Pixel sizes must be a power of two. Color QuickDraw supports pixel
- sizes of 1, 2, 4, and 8 bits; Color QuickDraw adds pixel sizes of 16 and 32
- bits.
- cmpCount
-
- cmpCount: With indexed pixels, each pixel is a single value representing an
- index into a color table, and therefore the cmpCount field of a PixMap record is
- 1—the index is the single component. With direct pixels, each pixel contains
- three components, one integer each for the intensities of red, green, and blue,
- and cmpCount is 3. Other values are undefined.
-
- cmpSize: The cmpSize field specifies the size of each component. A 32-bit pixel
- consists of three components (red, green, and blue values) of 8 bits each. Since
- cmpCount * cmpSize (3 * 8 = 24) is less than the value of pixelSize, 8 bits in
- the pixel are not part of any component. These bits are unused: Color QuickDraw
- sets them to zero in any image it creates, and if presented with a 32-bit image,
- for example in CopyBits, it passes whatever bits are there. (Generally,
- therefore, your application should clear image memory to 0 before creating a
- 32-bit image.)
-
- A 16-bit pixel consists of three components of 5 bits each. This leaves an
- unused high-order bit, which QuickDraw sets to 0.
-
- Color QuickDraw expects that the sizes of all components are the same, and that
- cmpCount * cmpSize is less than or equal to pixelSize.
-
- In each direct pixel, the pixel value is the concatenation of the red, green,
- and blue components, where red is in the most significant bits and blue is in
- the least significant. The entire direct pixel is right justified; unused bits
- occupy the highest-order bits.
- _______________________________________________________________________________
-
- æKY Direct…Pixel…Examples
- æC »Direct Pixel Examples Color QuickDraw
- _______________________________________________________________________________
-
- Figure 16-1 shows a 32-bit direct pixel value, in which the pixel and component
- fields have been set up as
-
- pixelType = 16; {RGBDirect}
- pixelSize = 32; {must be a power of 2}
- cmpCount = 3; {red, green, and blue values}
- cmpSize = 8; {8 bits for each component}
-
- ø 16.1 A 32-bit direct pixel
-
- In this example, the pixel value (hexadecimal) is $00178609, which deconstructs
- into component values of $17 red, $86 green, and $09 blue, resulting in a medium
- green. Figure 16-2 approximates the same color as in Figure 16-1 using a 16-bit
- pixel specified as follows:
-
- pixelType = 16; {RGBDirect}
- pixelSize = 16; {Must be a power of 2}
- cmpCount = 3; {red, green, and blue values}
- cmpSize = 5; {5 bits for each component}
-
- ø 16.2 A 16-bit direct pixel
-
- Here the pixel value is $0A01, with component values of $02, $10, and $01 for
- red, green and blue.
-
- When converting a 32-bit pixel value to 16 bits, the three least significant
- bits are dropped for each component. When converting a 16-bit pixel value to 32
- bits, the most significant three bits of each component are replicated and added
- to constitute the least significant three bits of the resulting 8-bit component,
- as illustrated in Figure 16-3.
-
- ø 16.3 Converting a 16-bit direct pixel to 32-bit direct
-
- In this way, white stays white, black stays black, and other values are spread
- appropriately.
-
- Figures 16-4 to 16-9 show first how Color QuickDraw converts a full 48-bit RGB
- color to 32, 16, and 8 bit values (the latter indexed), and then the reverse
- process, of converting those values back to 48 bits.
-
- ø 16.4 Converting a 48-bit RGB value to 32-bit direct
-
- A 32-bit direct pixel uses the most significant 8 bits of each component, and
- has an 8-bit pad.
-
- ø 16.5 Converting a 48-bit RGB value to 16-bit direct
-
- A 16-bit direct pixel uses the most significant 5 bits of each component, and
- has a 1-bit pad.
-
- ø 16.6 Converting a 48-bit value to an 8 bit index
-
- To obtain an 8-bit pixel value, the Color Manager determines the closest RGB
- value in the CLUT; its index value is stored in the 8-bit pixel. In the standard
- 8-bit CLUT, from 'CLUT' resource with ID of 8, the nearest value to the original
- RGB value of Figure 16-4 is in table entry 161. Note that with indexed pixels,
- the pixel value has no direct relation to the original RGB value.
-
- ø 16.7 Converting an 32-bit pixel to 48 bits
-
- Color QuickDraw expands a 32-bit pixel into a 48-bit value by dropping the pad
- byte and doubling each 8-bit component. Note that the resulting 48-bit value
- differs (in the least significant 8 bits of each component) from the original in
- Figure 16-4.
-
- ø 16.8 Converting an 16-bit pixel to 48 bits
-
- Color QuickDraw expands a 16-bit pixel into a 48-bit value by dropping the pad
- bit and inserting three copies of each 5-bit component and a copy of the most
- significant bit into each 16-bit component of the destination. Note that the
- result differs (in the least significant 11 bits of each component) from the
- original value.
-
- ø 16.9 Converting an 8-bit indexed pixel to 48 bits
-
- Color QuickDraw expands an 8-bit indexed pixel into a 48-bit value by taking the
- 48-bit value pointed to in the CLUT. The difference between this value and the
- original 48-bit value varies, depending on the CLUT values.
-
- _______________________________________________________________________________
-
- æKY PICT…Extensions
- æC »PICT Extensions Color QuickDraw
- _______________________________________________________________________________
-
- The PICT2 picture format defined for Color QuickDraw only supports images
- consisting of CLUT indices. The PICT2 format has been expanded so that it can
- record images with pixels that directly specify a given color.
-
- To the current imaging opcodes BitsRect, BitsRgn, PackBitsRect, and PackBitsRgn,
- Color QuickDraw adds DirectBitsRect and DirectBitsRgn. These opcodes enable your
- application to cut, paste, and store images with up to 32 bits of color
- information per pixel.
-
- A new routine, the OpenCPicture function, lets your application create a PICT2
- file and pass rectangle and resolution information, which is stored in the PICT2
- header. This provides a simple mechanism for creating images with spatial
- resolution other than 72 dpi. The OpenCPicture function is described in “New
- Color QuickDraw Routines” later in this chapter.
-
- The following opcodes occur only in pictures using the extended PICT2 format.
- Two new opcodes specify direct pixels:
-
- DirectBitsRect EQU $9A ; direct data copybits, rect clipped
- DirectBitsRgn EQU $9B ; direct data copybits, rgn clipped
-
- In addition, an opcode has been defined to specify font information:
-
- FontName EQU $2C ; font ID and name
-
- The PICT2 format is described fully in “The Extended PICT2 Format.”
- _______________________________________________________________________________
-
- æKY Well-Behaved…Graphics…Applications
- æC »WELL-BEHAVED GRAPHICS APPLICATIONS Color QuickDraw
- _______________________________________________________________________________
-
- Over the years, some developers have written applications that modify the
- QuickDraw data structures directly rather than using the routines provided for
- that purpose. Then, when Apple engineers improve QuickDraw, the applications
- break.
-
- As both QuickDraw and graphics applications grow more complex, the problem
- becomes acute. This section points to new routines you can use to signal
- QuickDraw when your application modifies certain data structures directly so
- that QuickDraw can take note and act accordingly.
-
- Applications should not directly change fields in QuickDraw data structures, but
- use the following procedures instead:
-
-
- AddComp AddSearch BackColor
- BackPat BackPixPat CharExtra
- ClipRect ColorBit CopyPixPat
- DelComp DelSearch ForeColor
- GrafDevice HideCursor HidePen
- HiliteColor MakeRGBPat Move
- MovePortTo MoveTo ObscureCursor
- OpColor PenMode PenNormal
- PenPat PenPixPat PenSize
- PortSize RGBBackColor RGBForeColor
- SetCCursor SetClientID SetClip
- SetCursor SetDeviceAttribute SetGDevice
- SetOrigin SetPenState SetPort
- SetPortBits SetPortPix ShowCursor
- ShowPen SpaceExtra TextFace
- TextFont TextMode TextSize
-
- Using these routines rather than directly modifying the data structures ensures
- that your application will fully benefit from any future improvements to
- QuickDraw. In particular, the OffscreenGWorld routines described in the Graphics
- Devices Manager chapter of this volume remove much of the need for directly
- modifying graphics data structures.
-
- Apple strongly recommends that new applications follow these guidelines.
- However, it is possible to make existing applications better-behaved by calling
- one of the following procedures after directly changing a QuickDraw data
- structure and before making any other QuickDraw call:
-
- CTabChanged
- PixPatChanged
- PortChanged
- GDeviceChanged
-
- These routines inform QuickDraw that a direct modification has occurred so it
- can update its world. They are described in the “New Color QuickDraw
- Routines”section.
-
- _______________________________________________________________________________
-
- æKY Using…Color…Quickdraw…Vol…VI
- æC »USING COLOR QUICKDRAW Color QuickDraw
- _______________________________________________________________________________
-
- If your application uses color in straightforward ways it will probably execute
- without change in a direct pixel environment.
-
- For most other applications, the main concern is in the creation and use of
- special-purpose PixMap and GDevice records—and by using the OffscreenGWorld
- routines described in the Graphics Devices Manager chapter you will find such
- tasks far easier than before.
-
- If you must work with GrafPort, PixMap, and GDevice records in ways beyond the
- scope of the OffscreenGWorld routines, the following guidelines may aid you in
- adapting to Color QuickDraw’s direct pixel environment:
-
- • Don’t draw directly to the screen. A screen baseAddr is only guaranteed
- to be a valid pointer in 32-bit addressing mode.
-
- • Don’t directly change the fgColor or bkColor fields of a grafPort and
- expect them to be used as the pixel values. Color QuickDraw recalculates
- these values for each device. If you really want to draw in an index
- instead of a color, use a palette with pmExplicit colors, as described in
- the Palette Manager chapter in this volume. For device independant colors
- use the RGBForeColor and RGBBackColor procedures.
-
- • Fill out all the fields in a new PixMap record. The NewPixMap function
- returns a PixMap record that has been cloned from TheGDevice record’s
- PixMap record. If you don’t want a copy of the main screen’s PixMap
- record—for example, you want one that is a different depth—then you must
- fill out more fields than just pixelSize: you must fill out the
- pixelType, cmpCount, and cmpSize fields. Set pmVersion to 0 when
- initializing your own PixMap record. For future compatibility you should
- also set packType, packSize, planeBytes, and pmReserved to 0.
-
- • Don’t clone a graphic device record’s PixMap record. Instead, use the
- NewPixmap function or the CopyPixMap procedure. If you must create or
- manually clone a PixMap record, make sure to set the pmVersion field and
- other unused fields to 0 for future compatibility.
-
- • Fill out all the fields of a new GDevice. When creating an offscreen
- graphic device record by calling NewGDevice with a mode of -1, you must
- fill out the fields of the graphic device record (for instance, gdType)
- yourself. If you want a copy of an existing graphic device record, then
- copy the gdType field from it. If you explicitly want an indexed device
- then, set gdType to 0.
- • Don’t assume a PixMap record has a CLUT. Direct PixMap records need not
- have CLUTs. For compatibility, direct PixMap records should have dummy
- pmTable handles that point to color table headers with seed values equal
- to cmpSize * cmpCnt, and the ctSize field should be set to 0.
-
- Again, all these problems are eased if you use the OffscreenGWorld routines.
-
- _______________________________________________________________________________
-
- æKY Copying…PixMap…Records
- æC »Copying PixMap Records Color QuickDraw
- _______________________________________________________________________________
-
- PixMap records are copied using the current GDevice record (pointed to by the
- TheGDevice global variable) to determine the destination color information.
- Consequently, whenever copying to an offscreen PixMap record with
- characteristics differing from those of the current GDevice record (which is
- usually the main screen), you should create an appropriate offscreen graphic
- device record and set it as the current graphic device record before the copy.
- If an offscreen PixMap record is only copied from, then no offscreen graphic
- device record is needed since Color QuickDraw obtains the source color
- information from the source PixMap record. (See the Graphic Devices Manager
- chapter for information about offscreen graphics routines and data structures.)
- _______________________________________________________________________________
-
- æKY Dithering
- æC »Dithering Color QuickDraw
- _______________________________________________________________________________
-
- The CopyBits procedure now provides a new dither copy mode.
-
- Copying using CopyBits from any PixMap record to an indexed device works in one
- of two ways:
-
- • If the transfer mode is DitherCopy, then CopyBits does its best to
- provide error diffusion during the copy operation. As with arithmetic
- transfer modes, hidden colors are ignored, so that color matching is
- limited by the resolution of the inverse table for the destination
- graphics device. (See the discussion of hidden colors in the Inverse
- Table section of the Color Manager chapter, Inside Macintosh, Volume V.)
- DitherCopy provides good results for most images, but does have
- drawbacks. A clipped DitherCopy does not provide pixel-for-pixel
- equivalence to the same unclipped DitherCopy—thus updates are not
- equivalent to saving the bits behind, and clipped XOR copies will not
- perform as erases.
-
- Currently, if a color search procedure is present, copy mode is used
-
- instead of dither mode. (This may change in future versions.)
-
- • If you copy from any PixMap record to an indexed device using the classic
- copy mode, color mapping is done on a pixel-by-pixel basis—no errors are
- accumulated and hidden colors are ignored. If a color search procedure is
- present, it is called on a pixel-by-pixel basis.
-
- If you copy from any PixMap record to a direct device, dithering is never done,
- since dithering is generally useful only when copying to a destination with a
- lower color resolution than the source. If the destination device is 16-bits or
- 32-bits per pixel, then no error diffusion is performed. You can use dithering
- when copying between indexed PixMap records, such as from an 8-bit pixel depth
- to a 4-bit depth, or between two 8-bit PixMap records with different color
- tables.
-
- _______________________________________________________________________________
-
- æKY Resizing…Images
- æC »Resizing Images Color QuickDraw
- _______________________________________________________________________________
-
- When copying from direct pixel maps, if the destination rectangle is smaller
- than the source rectangle, Color QuickDraw uses an averaging technique to
- provide destination pixels, maintaining high-quality images when shrinking.
- Pixel averaging is also performed when shrinking indexed images using dither
- copy modes, regardless of the destination.
-
- _______________________________________________________________________________
-
- æKY Luminance…Mapping
- æC »Luminance Mapping Color QuickDraw
- _______________________________________________________________________________
-
- When the user sets a screen device to a gray-scale mode, Color QuickDraw places
- an evenly spaced set of grays in the device CLUT such that they form a linear
- ramp from white to black.
-
- When Color QuickDraw displays a color on a graphics device whose pmTable
- contains only grays (ignoring entries used for animation), it computes the
- luminance of the desired color and uses that to determine the appropriate gray
- value to draw.
-
- To facilitate the creation of grayscale devices, the GetCTable function has been
- enhanced to recognize additional standard CLUT IDs. As described in Volume V,
- the GetCTable function looks like this:
-
- FUNCTION GetCTable (ctID: Integer) : CTabHandle;
-
- The default grayscale CLUT for a given pixel depth can be obtained by calling
- GetCTable with a ctID value of PixelSize +32.
-
- PixelSize CLUT ID Color Table Composition
- 2 34 black, white, 33% gray, 66% gray
- 4 36 black, 14 shades of gray, white
- 8 40 black, 254 shades of gray, white
-
- The equivalent default color tables can be obtained by adding 64 to the bit
- depth, as described in the Palette Manager chapter.
-
- PixelSize CLUT ID Color Table Composition
- 2 66 black, white, 50% gray, highlight
- 4 68 black, 14 colors including a highlight, white
- 8 72 black, 254 colors including a highlight, white
- _______________________________________________________________________________
-
- æKY Image…Resolution
- æC »Image Resolution Color QuickDraw
- _______________________________________________________________________________
-
- Color QuickDraw supports pixel maps of resolutions other than 72 dots per inch
- (dpi). In the past, applications have accepted pixel maps of a certain number of
- rows and columns and assumed that they were generated on a 72 dpi device. Such
- pixel maps were usually copied and printed at a 72 dpi resolution, lending the
- impression that QuickDraw could not handle pixel maps of higher density.
-
- With the advent of frame grabbers and scanners, many pixel maps have resolutions
- of 150, 200, 300 dpi, or greater. A user expects pixel maps to display an
- approximation of the information on a 72 dpi display but print on a higher
- resolution device to the best of the device's ability.
-
- _______________________________________________________________________________
-
- æKY Importing…PixMap…Records
- æC »Importing PixMap Records Color QuickDraw
- _______________________________________________________________________________
-
- The resolution of a PixMap record is contained in the hRes and vRes fields.
- These values are fixed point numbers in dots per inch. When importing pictures,
- applications should check the picture type to see if it was created with
- OpenCPicture.
-
- An alternative is to replace the StdBits bottleneck during playback. When the
- bottleneck procedure is called, you should
-
- 1. check to guarantee that the source is a PixMap record by checking the high
- bit of the PMVersion(rowBytes) field
-
- 2. read the hRes and vRes information out of the source PixMap record
-
- At this point, the source rect field indicates the size of the source in pixels
- at the resolution specified by the hRes and vRes fields. To display it at
- another resolution, your application should compute the dest rect field value
- appropriately. For example if the source resolution is 300 dpi and the intention
- is to display it at 75 dpi, then the destination rectangle width and height
- should be computed as 1/4 of that of the source.
- _______________________________________________________________________________
-
- æKY Exporting…PixMap…Records
- æC »Exporting PixMap Records Color QuickDraw
- _______________________________________________________________________________
-
- When exporting PixMap records, your application should ensure that the hRes and
- vRes fields accurately reflect the image data. During picture recording, the
- destination rectangle of the CopyBits call should be appropriate for display at
- 72 dpi. If you want an entire picture to be a different resolution, use the
- OpenCPicture function.
-
- _______________________________________________________________________________
-
- æKY Converting…a…Bitmap…to…a…Region
- æC »Converting a Bitmap to a Region Color QuickDraw
- _______________________________________________________________________________
-
- A new function, BitMapToRegion, converts a bitmap to a region. If you used the
- PaintRgn procedure on the converted region, the resulting region would be the
- same as the bitmap. This procedure may be useful if you want to test the mouse
- for hits against the black pixels in a bitmap, or drag the outline of a bitmap
- using DragGrayRegion.
- _______________________________________________________________________________
-
- æKY Checking…that…QuickDraw…is…Done
- æC »Checking that QuickDraw is Done Color QuickDraw
- _______________________________________________________________________________
-
- A new function, QDDone, checks to see whether QuickDraw drawing operations have
- completed in a grafport. This is useful if you are executing in an environment
- with a graphics accelerator, where drawing operations may proceed
- asynchronously.
-
- _______________________________________________________________________________
-
- æKY New…Color…Quickdraw…Routines
- æC »NEW COLOR QUICKDRAW ROUTINES Color QuickDraw
- _______________________________________________________________________________
-
- Since using direct color only requires internal Color QuickDraw changes to
- recognize direct pixel values, no new routines are defined for direct color.
- _______________________________________________________________________________
-
- æKY New…QuickDraw…Result…Codes
- æC »New QuickDraw Result Codes Color QuickDraw
- _______________________________________________________________________________
-
- QuickDraw uses stack space for work buffers. For complex operations such as
- depth conversion, dithering, or image resizing, stack space may not be
- sufficient. Color QuickDraw now attempts to get temporary memory from
- MultiFinder. If that is still not enough, or if MultiFinder is not present,
- Color QuickDraw returns
-
- QDErr -149 Insufficient stack
-
- One recourse for the application is to divide the operation—for example divide
- the image into left and right halves—and try again. An alternative is to make
- the stack larger.
-
- While recording drawing operations into an open region the resulting region
- description might overflow the 64 KB limit. Should this happen Color QuickDraw
- will return -147 in QDErr:
-
- QDErr -147 Region too big
-
- Since the resulting region is potentially corrupt, closeRgn returns an empty
- region if it detects QDErr has been set to -147.
-
- _______________________________________________________________________________
-
- æKY Creating…an…Extended…PICT2…Picture
- æC »Creating an Extended PICT2 Picture Color QuickDraw
- _______________________________________________________________________________
-
- FUNCTION OpenCPicture (newHeader: PICT2Header) : PicHandle;
-
- OpenCPicture performs the same functions as OpenPicture, except that it creates
- an extended PICT2 format file, with pixel resolution and the best imaging
- rectangle stored in the header.
-
- You pass a PICT2Header record describing the rectangle that encloses the drawing
- information you supply for the picture, and you pass horizontal and vertical
- resolutions describing the best resolution for displaying the picture in the
- rectangle. The structure of a PICT2Header record is
-
- PICT2Header =
- RECORD
- SrcRect: Rect {source rectangle for best display}
- {at HRes, VRes resolution}
- hRes: Fixed; {best horizontal resolution}
- vRes: Fixed; {best vertical resolution}
- version: word; {set to -2}
- reserved: word; {reserved for future use}
- END;
-
- Note that the order the information is recorded in the PICT2 header differs from
- the order in this record. See the sample PICT2 file in “The Extended PICT2
- Format.”
-
- As with OpenPicture, you close the picture using ClosePicture, and draw it using
- DrawPicture.
-
- _______________________________________________________________________________
-
- æKY From…Bitmap…to…Region
- æC »From Bitmap to Region Color QuickDraw
- _______________________________________________________________________________
-
- FUNCTION BitMapToRegion (region:RGNHandle; bMap:BitMap) : OSErr;
-
- The region parameter must be a valid region handle created with a NewRgn
- function. The old region contents are lost.
-
- The bMap parameter may either be a BitMap or PixMap record. If a PixMap record
- is passed, its pixel size (bits per pixel) must be 1.
-
- Result codes
- rgnTooBigErr -500 BitMap would convert into a region greater
- than 32 KB
- pixmapTooDeepErr -148 PixMap record is deeper than 1 bit per pixel
- _______________________________________________________________________________
-
- æKY Drawing…Completion
- æC »Drawing Completion Color QuickDraw
- _______________________________________________________________________________
-
- FUNCTION QDDone (port:GrafPtr) : Boolean;
-
- The QDDone function returns true if drawing operations have completed in the
- designated port, false if any remain to be executed. This call may be useful if
- a graphics accelerator is present and operating asynchronously. You can ensure
- that all drawing has been done and avoid the possibility that new drawing
- operations might be overlaid by previously issued but unexecuted operations.
-
- _______________________________________________________________________________
-
- æKY Reporting…Data…Structure…Changes
- æC »Reporting Data Structure Changes Color QuickDraw
- _______________________________________________________________________________
-
- The following routines can be used to mitigate possible side effects of directly
- changing a CLUT, PixPat, GrafPort, or GDevice data structure.
-
- PROCEDURE CTabChanged (ctab: CTabHandle);
-
- Call CTabChanged after modifying the content of a color table. CTabChanged calls
- GetCTSeed to get a new seed for the color table and notifies QuickDraw of the
- change.
-
- PROCEDURE PixPatChanged (ppat: PixPatHandle);
-
- Call PixPatChanged after modifying a PixPat data structure or any of its
- substructures (patMap or patData records). PixPatChanged sets the patXValid flag
- to -1 and notifies QuickDraw of the change.
-
- If your application changes the pmTable field of the pixel pattern’s patMap, it
- should call PixPatChanged. However, if your application changes the content of
- the CLUT referenced by pmTable, it should call CTabChanged as well.
-
- PROCEDURE PortChanged (port: GrafPtr);
-
- Call PortChanged after modifying the content of a port or any of its
- substructures. PortChanged notifies QuickDraw of the change.
-
- None of the PixPat records pointed to by a CGrafPort record should be changed
- directly. Use PenPixPat and BackPixPat instead. However, if your application
- changes the content of one of the PixPat records, it should call PixPatChanged.
-
- If your application changes the pmTable field of the port’s PixMap, it should
- call PortChanged. However, if your application changes the content of the color
- table referenced by pmTable, it should call CTabChanged as well.
-
- PROCEDURE GDeviceChanged (gdh: GDHandle);
-
- Call GDeviceChanged after modifying a gDevice graphics device record or any of
- its substructures. GDeviceChanged notifies QuickDraw of the change.
-
- If your application changes the pmTable field of the graphics device record’s
- PixMap, it should call GDeviceChanged. However, if your application changes the
- content of the color table referenced by gdPMap, it should call CTabChanged as
- well.
-
- _______________________________________________________________________________
-
- æKY The…Extended…PICT2…Format
- æC »THE EXTENDED PICT2 FORMAT Color QuickDraw
- _______________________________________________________________________________
-
- The PICT2 format presented in the Color QuickDraw chapter of Volume V has been
- extended to allow storing direct PixMaps and for maintaining resolution and
- imaging rectangle information.
-
-
- The major differences between version 1 and version 2 pictures are that three
- opcodes previously listed as reserved have been defined, and one defined opcode
- has been redefined:
-
- Opcode 2C signals font name information.
-
- Opcodes 9A and 9B now define direct-pixel pictures, with PixMaps containing
- three components, directly specifying RGB values.
-
- Opcode 0C00 still signifies a header record, and it is still 24 bytes, but the
- contents have changed.
-
- This section presents a sample PICT file and the extended PICT2 opcodes.
-
- _______________________________________________________________________________
-
- æKY Sample…Extended…PICT2…File
- æC »Sample Extended PICT2 File Color QuickDraw
- _______________________________________________________________________________
-
- An example of an extended PICT2 data file that can display a single direct-pixel
- image is shown in Table 1.
-
- Table 1. PICT file example
- ________________________________________________________________________
- Size Name Description
- (in bytes)
- 2 picSize low word of picture size
- 8 picFrame rectangular bounding box of picture, at
- 72 dpi
-
- Picture Definition Data:
-
- 2 version op version opcode = $0011
- 2 version version number = $02FF
- 2 Header op header opcode = $0C00
- 2 version set to -2 for extended PICT2
- 2 reserved reserved for future Apple use
- 4 HRes native horizontal resolution
- 4 VRes native vertical resolution
- 8 SrcRect native source rectangle
- 4 reserved reserved for future Apple use
- 2 opbitsRect bitMap opcode = $009A for direct
- 4 baseAddr for direct must be $000000FF. See Table 4
- 2 rowBytes integer, must have high bit set to signal pixMap
- 8 bounds rectangle, bounding rectangle at source resolution
- 2 pmVersion integer, pixMap version number = 0
- 2 packType integer, defines packing format
- 4 packSize LongInt, length of pixel data = 0
- 4 hRes fixed, horizontal resolution (dpi) of source data,
- normally $00480000 (72 dpi)
- 4 vRes fixed, vertical resolution (dpi) of source data,
- normally $00480000 (72 dpi)
- 2 pixelType integer, defines pixel type; 16 for direct
- 2 pixelSize integer, number of bits in pixel; 16 or 32 for direct
- 2 cmpCount integer, number of components in pixel; 3 for direct
- 2 cmpSize integer, number of bits per component; 5 or 8 for direct
- 4 planeBytes LongInt, offset to next plane = 0
- pmTable color table = 0
- pmReserved reserved = 0
- 4 ctSeed LongInt, color table seed
- 2 ctFlags integer, flags for color table
- 2 ctSize integer, number of entries in ctTable –1
- (ctSize+1) * 8 ctTable color lookup table data
- 8 srcRect rectangle, source rectangle at source resolution
- 8 dstRect rectangle, destination rectangle at 72 dpi resolution
- 2 mode integer, transfer mode see Table 5
- pixData pixel data
- 2 endPICT op end-of-picture opcode = $00FF
-
- _______________________________________________________________________________
-
- æKY PICT2…Opcode…Types
- æC »PICT2 Opcode Types Color QuickDraw
- _______________________________________________________________________________
-
- The following description shows the new PICT2 format, with changes from the
- description in Volume V indicated by an asterisk.
-
-
- The opcode information in Table 3x is provided for the purpose of debugging
- application-generated PICT files. Your application should generate and read PICT
- files only by using standard QuickDraw or Color QuickDraw routines (OpenPicture,
- OpenCPicture, ClosePicture). The data types listed in Table 2x are used in the
- Table 3x opcode definitions.
-
- Table 2. Data types
- ________________________________________________________________________
- Type Size
- v1 opcode 1 byte
- v2 opcode 2 bytes
- integer 2 bytes
- long integer 4 bytes
- mode 2 bytes
- point 4 bytes
- 0..255 1 byte
- –128..127 1 byte (signed)
- rect 8 bytes (top, left, bottom, right: integer)
- poly 10+ bytes
- region 10+ bytes
- fixed-point number 4 bytes
- pattern 8 bytes
- rowbytes 2 bytes (always an even quantity)
- ________________________________________________________________________
-
- _______________________________________________________________________________
-
- æKY Extended…PICT2…Opcodes
- æC »Extended PICT2 Opcodes Color QuickDraw
- _______________________________________________________________________________
-
- Valid picture opcodes are listed in Table 3. New opcodes or those altered to
- extend the PICT2 format are indicated by a leading asterisk (*). The unused
- opcodes found throughout the table are reserved for Apple use. The length of the
- data that follows these opcodes is pre-defined, so if they are encountered in
- pictures, they can simply be skipped. By default, QuickDraw reads and then
- ignores these opcodes.
-
-
-
- Table 3. PICT opcodes
- ________________________________________________________________________
- Opcode Name Description Data Size
- (in bytes)
- $0000 NOP nop 0
- $0001 Clip clip region size + data
- $0002 BkPat background pattern 8
- $0003 TxFont text font (word) 2
- $0004 TxFace text face (byte) 1
- $0005 TxMode text mode (word) 2
- $0006 SpExtra space extra (fixed point) 4
- $0007 PnSize pen size (point) 4
- $0008 PnMode pen mode (word) 2
- $0009 PnPat pen pattern 8
- $000A FillPat fill pattern 8
- $000B OvSize oval size (point) 4
- $000C Origin dh, dv (word) 4
- $000D TxSize text size (word) 2
- $000E FgColor foreground color (long) 4
- $000F BkColor background color (long) 4
- $0010 TxRatio numer (point), denom (point) 8
- $0011 Version version (byte) 1
- $0012 BkPixPat color background pattern variable:
- see Table 4
- $0013 PnPixPat color pen pattern variable:
- see Table 4
- $0014 FillPixPat color fill pattern variable:
- see Table 4
- $0015 PnLocHFrac fractional pen position 2
- $0016 ChExtra extra for each character 2
- $0017 reserved opcode 0
- $0018 reserved opcode 0
- $0019 reserved opcode 0
- $001A RGBFgCol RGB foreColor variable:
- see Table 4
- $001B RGBBkCol RGB backColor variable:
- see Table 4
- $001C HiliteMode hilite mode flag 0
- $001D HiliteColor RGB hilite color variable:
- see Table 4
- $001E DefHilite Use default hilite color 0
- $001F OpColor RGB OpColor for variable:
- arithmetic modes see Table 4
- $0020 Line pnLoc (point), newPt (point) 8
- $0021 LineFrom newPt (point) 4
- $0022 ShortLine pnLoc (point, dh, dv 6
- (-128..127)
- $0023 ShortLineFrom dh, dv (-128..127) 2
- $0024 reserved opcode + 2 bytes data 2+ data
- length + data length
- $0025 reserved opcode + 2 bytes data 2+ data
- length + data length
- $0026 reserved opcode + 2 bytes data 2+ data
- length + data length
- $0027 reserved opcode + 2 bytes data 2+ data
- length + data length
- $0028 LongText txLoc (point), count 5 + text
- (0..255), text
- $0029 DHText dh (0..255), count 2 + text
- (0..255), text
- $002A DVText dv (0..255), count 2 + text
- (0..255), text
- $002B DHDVText dh, dv (0..255), count 3 + text
- (0..255), text
- $002C *fontName data length (word), old font 5+ name
- ID (word), name length (byte), length
- font name
- $002D reserved opcode + 2 bytes data 2+ data
- length + data length
- $002E reserved opcode + 2 bytes data 2+ data
- length + data length
- $002F reserved opcode + 2 bytes data 2+ data
- length + datalength
- $0030 frameRect rect 8
- $0031 paintRect rect 8
- $0032 eraseRect rect 8
- $0033 invertRect rect 8
- $0034 fillRect rect 8
- $0035 reserved opcode + 8 bytes data 8
- $0036 reserved opcode + 8 bytes data 8
- $0037 reserved opcode + 8 bytes data 8
- $0038 frameSameRect rect 0
- $0039 paintSameRect rect 0
- $003A eraseSameRect rect 0
- $003B invertSameRect rect 0
- $003C fillSameRect rectangle 0
- $003D reserved opcode 0
- $003E reserved opcode 0
- $003F reserved opcode 0
- $0040 frameRRect rect (see Note # 5 ) 8
- $0041 paintRRect rect (see Note # 5 ) 8
- $0042 eraseRRect rect (see Note # 5 ) 8
- $0043 invertRRec rect (see Note # 5 ) 8
- $0044 fillRRect rect (see Note # 5 ) 8
- $0045 reserved opcode + 8 bytes data 8
- $0046 reserved opcode + 8 bytes data 8
- $0047 reserved opcode + 8 bytes data 8
- $0048 frameSameRRect rect 0
- $0049 paintSameRRect rect 0
- $004A eraseSameRRect rect 0
- $004B invertSameRRect rect 0
- $004C fillSameRRect rect 0
- $004D reserved opcode 0
- $004E reserved opcode 0
- $004F reserved opcode 0
- $0050 frameOval rect 8
- $0051 paintOval rect 8
- $0052 eraseOval rect 8
- $0053 invertOval rect 8
- $0054 fillOval rect 8
- $0055 reserved opcode + 8 bytes data 8
- $0056 reserved opcode + 8 bytes data 8
- $0057 reserved opcode + 8 bytes data 8
- $0058 frameSameOval rect 0
- $0059 paintSameOval rect 0
- $005A eraseSameOval rect 0
- $005B invertSameOval rect 0
- $005C fillSameOval rect 0
- $005D reserved opcode 0
- $005E reserved opcode 0
- $005F reserved opcode 0
- $0060 frameArc rect, startAngle, arcAngle 12
- $0061 paintArc rect, startAngle, arcAngle 12
- $0062 eraseArc rect, startAngle, arcAngle 12
- $0063 invertArc rect, startAngle, arcAngle 12
- $0064 fillArc rect, startAngle, arcAngle 12
- $0065 reserved opcode + 12 bytes 12
- $0066 reserved opcode + 12 bytes 12
- $0067 reserved opcode + 12 bytes 12
- $0068 frameSameArc rect 4
- $0069 paintSameArc rect 4
- $006A eraseSameArc rect 4
- $006B invertSameAr rect 4
- $006C fillSameArc rect 4
- $006D reserved opcode + 4 bytes 4
- $006E reserved opcode + 4 bytes 4
- $006F reserved opcode + 4 bytes 4
- $0070 framePoly poly polygon size
- $0071 paintPoly poly polygon size
- $0072 erasePoly poly polygon size
- $0073 invertPoly poly polygon size
- $0074 fillPoly poly polygon size
- $0075 reserved opcode + poly
- $0076 reserved opcode + poly
- $0077 reserved opcode word + poly
- $0078 frameSamePoly (not yet implemented: 0
- same as 70, etc)
- $0079 paintSamePoly (not yet implemented) 0
- $007A eraseSamePoly (not yet implemented) 0
- $007B invertSamePoly (not yet implemented) 0
- $007C fillSamePoly (not yet implemented) 0
- $007D reserved opcode 0
- $007E reserved opcode 0
- $007F reserved opcode 0
- $0080 frameRgn rgn region size
- $0081 paintRgn rgn region size
- $0082 eraseRgn rgn region size
- $0083 invertRgn rgn region size
- $0084 fillRgn rgn region size
- $0085 reserved opcode + rgn region size
- $0086 reserved opcode + rgn region size
- $0087 reserved opcode + rgn region size
- $0088 frameSameRgn (not yet implemented- 0 same as 80, etc.)
- $0089 paintSameRgn (not yet implemented) 0
- $008A eraseSameRgn (not yet implemented) 0
- $008B invertSameRgn (not yet implemented) 0
- $008C fillSameRgn (not yet implemented) 0
- $008D reserved opcode 0
- $008E reserved opcode 0
- $008F reserved opcode 0
- $0090 BitsRect copybits, rect clipped variable:
- see Table 4
- $0091 BitsRgn copybits, rgn clipped variable:
- see Table 4
- $0092 reserved opcode + 2 bytes data 2+ data
- length + data length
- $0093 reserved opcode + 2 bytes data 2+ data
- length + data length
- $0094 reserved opcode + 2 bytes data 2+ data
- length + data length
- $0095 reserved opcode + 2 bytes data 2+ data
- length + data length
- $0096 reserved opcode + 2 bytes data 2+ data
- length + data length
- $0097 reserved opcode + 2 bytes data 2+ data
- length + data length
- $0098 PackBitsRect packed copybits, rect variable:
- clipped see Table 4
- $0099 PackBitsRgn packed copybits, rect variable:
- clipped see Table 4
- $009A *DirectBitsRect PixMap, srcRect, dstRect, mode variable
- (Word), PixData see Table 4
- $009B *DirectBitsRgn PixMap, srcRect, dstRect, mode variable
- (Word), maskRgn, PixData see Table 4
- $009C reserved opcode + 2 bytes data 2+ data
- length + data length
- $009D reserved opcode + 2 bytes data 2+ data
- length + data length
- $009E reserved opcode + 2 bytes data 2+ data
- length + data length
- $009F reserved opcode + 2 bytes data 2+ data
- length + data length
- $00A0 ShortComment kind (word) 2
- $00A1 LongComment kind (word), size 4+data
- (word), data
- $00A2 reserved opcode + 2 bytes data 2+ data
- length + data length
- : : :
- : : :
- $00AF reserved opcode + 2 bytes data 2+ data
- length + data length
- $00B0 reserved opcode 0
- : : :
- : : :
- $00CF reserved opcode 0
- $00D0 reserved opcode + 4 bytes data 4+ data
- length + data length
- : : :
-
- : : :
-
- $00FE reserved opcode + 4 bytes data 4+ data
- length + data length
- $00FF opEndPic end of picture 2
- $0100 reserved opcode + 2 bytes data 2
- : : :
- : : :
-
- $01FF reserved opcode + 2 bytes data 2
- $0200 reserved opcode + 4 bytes data 4
- : : :
-
- $0BFF reserved opcode + 4 bytes data 22
- $0C00 *HeaderOp Version (word), reserved 24
- (word), Hres, VRes (Fixed),
- SrcRect (Rect), reserved (Long)
- $0C01 reserved opcode + 4 bytes data 24
- : : :
-
- $7F00 reserved opcode + 254 bytes data 254
- : : :
-
- $7FFF reserved opcode + 254 bytes data 254
- $8000 reserved opcode 0
- : : :
-
- $80FF reserved opcode 0
- $8100 reserved opcode + 4 bytes data 4+ data
- length + data length
- : : :
-
- $FFFF reserved opcode + 4 bytes data 4+ data
- length + data length
- ________________________________________________________________________
-
- Notes to Table 3
-
- 1. Remember, opcode size is 1 byte for PICT, 2 bytes for PICT2.
-
- 2. Because opcodes must be word aligned in version 2 pictures, a byte of 0
- (zero) data is added after odd-size data.
-
- 3. The size of reserved opcodes has been defined. They can occur only in version
- 2 pictures.
-
- 4. All unused opcodes are reserved for future Apple use and should not be used.
-
- 5. For opcodes $0040–$0044: rounded-corner rectangles use the setting of the
- ovSize point (refer to opcode $000B)
- 6. For opcodes $0090 and $0091: data is unpacked. These opcodes can only be used
- for rowbytes less than 8.
-
- 7. For opcodes $0100–$7FFF: the amount of data for opcode $nnXX = 2 * nn bytes.
-
-
-
- The New Opcodes: Expanded Format
-
- The expanded format of the version 2 PICT opcodes is shown in Table 4 below.
-
- Table 4. Data Format of Version 2 PICT Opcodes
- ________________________________________________________________________
- Opcode Name Description Reference
- to Notes
-
- $002C fontName ID and name of font See Note 1
- $009A DirectBitsRect PixMap, src and dst See Note 2
- rects, mode, and PixData
- $009B DirectBitsRgn PixMap, src and dst See Note 2
- rects, mode, maskRgn,
- PixData
- $0C00 HeaderOp Version (Word), reserved Word, See Note 3
- Hres, VRes (Fixed), SrcRect
- (Rect), reserved (Word)
-
- ________________________________________________________________________
-
- Notes to Table 4
-
- 1. The fontName information begins with a word containing the field’s data
- length, followed by a word containing the old font ID, a byte containing the
- length of the font name, and the font name itself.
-
-
- 2. Unlike previous Bits opcodes, the DirectBits opcodes store the baseAddr field
- of the pixMap structure in a PICT2. For compatibility with existing systems the
- baseAddr field is set to $000000FF. On systems without direct pixel support,
- opcodes $009A and $009B read a word from the picture and then skip that much
- data. The next opcode fetched from the picture is $00FF, which terminates
- picture playback.
-
-
- The DirectBitsRect opcode will be followed by this structure:
-
-
- pixMap: { described below }
- srcRect: Rect; { source rectangle }
- dstRect: Rect; { destination rectangle }
- mode: word; { transfer mode }
- pixData: { described below }
-
- The DirectBitsRgn opcode will be followed by this structure:
-
-
- pixMap: { described below }
- srcRect: Rect; { source rectangle }
- dstRect: Rect; { destination rectangle }
- mode: word; { transfer mode }
- maskRgn: Region; { region for masking }
- pixData: { described below }
-
- The following pseudocode describes the pixData data type.
-
-
- pixData:
-
- If packType = 1 (unpacked) or rowbytes < 8 then data is unpacked, and
- data size = rowBytes * (bounds.bottom-bounds.top);
-
- If packType = 2 (drop pad byte) then the high-order pad byte of a
- 32-bit direct pixel is dropped, and
- data size = (3/4) * rowBytes * (bounds.bottom-bounds.top);
-
- If packType > 2 (packed) then
- Image contains (bounds.bottom-bounds.top) packed scanlines
- Each scanline consists of [byteCount] [data].
- If rowBytes > 250 then byteCount is a word, else it is a byte.
-
- In a picture, the packType field of a pixMap specifies the manner in which the
- pixData was compressed. To facilitate banding of images when memory is short,
- all data compression is done on a scanline basis. The currently defined packing
- schemes are:
-
- 1 = no packing
-
- 2 = remove pad byte—supported only for 32-bit pixels (24-bit data)
-
- 3 = run length encoding by pixelSize chunks, one scanline at a time—supported
- only for 16-bit pixels
-
- 4 = run length encoding all of one component at a time, one scanline at a time,
- red component first—supported only for 32-bit pixels (24-bit data)
-
- For future compatibility, other packType values skip scanline data and draw
- nothing. Since pixMap data in memory is assumed to be unpacked regardless of the
- packType field value, packType can be used to tell the picture-recording
- mechanism what packing technique to use on that data. A packType value of zero
- in memory indicates that the default packing scheme should be used. As a general
- rule, using the default packing scheme is recommended. Currently, the default
- packType for pixelSize=16 is scheme 3, for pixelSize=32 it is scheme 4.
- Regardless of the setting of packType at the time of picture recording, the
- packType actually used to save the image will be recorded in the picture.
-
- Since each scanline of packed data is preceded by a byte count, packSize is not
- used and must be zero for future compatibility.
-
- When the pixel type is direct chunky, cmpCount * cmpSize ≤ pixelSize. For
- storing 24 bit data in a 32 bit pixel, cmpSize would be eight and cmpCount would
- be three. If you set cmpCount = 4 then the high byte will be compressed by
- packing scheme 4 and stored in the picture.
-
- 3. The headerOp information is passed to the OpenCPicture routine as a
- PictureHeader record, which has the structure:
-
- TYPE
- PictureHeader = Record
- version: word;
- reserved: word;
- HRes: Fixed;
- VRes: Fixed;
- SrcRect: Rect
- END;
-
-
- _______________________________________________________________________________
-
- æKY Summary…of…Color…Quickdraw…Vol…VI…Changes
- æC »SUMMARY OF COLOR QUICKDRAW CHANGES Color QuickDraw
- _______________________________________________________________________________
-
- The following cards summarize the constants, data types, and routines for Color
- Quickdraw.
- _______________________________________________________________________________
-
- æKY Color…Quickdraw…Constants
- æC »Constants Color QuickDraw
- _______________________________________________________________________________
-
- CONST
-
- {New Constants for Color QuickDraw}
-
- ditherCopy = 64; {Dither mode for Copybits}
- RGBDirect = 16; {16 & 32 bits/pixel pixelType value}
- _______________________________________________________________________________
-
- æKY Color…Quickdraw…Data…Types
- æC »Data Types Color QuickDraw
- _______________________________________________________________________________
-
- PICT2Header =
- RECORD
- version: word; {set to -2}
- reserved: word; {reserved for future use}
- hRes: Fixed; {best horizontal resolution}
- vRes: Fixed; {best vertical resolution}
- SrcRect: Rect {source rectangle for best display}
- {at hRes, vRes resolution}
- END;
- _______________________________________________________________________________
-
- æKY Color…Quickdraw…Vol…VI…Routines
- æC »Routines Color QuickDraw
- _______________________________________________________________________________
-
- FUNCTION OpenCPicture (newHeader: PICT2Header) : PicHandle;
- FUNCTION GetCTable (ctID: Integer) : CTabHandle;
- FUNCTION BitMapToRegion (region:RGNHandle; bMap:BitMap) : OSErr;
- PROCEDURE CTabChanged (ctab: CTabHandle);
- PROCEDURE PixPatChanged (ppat: PixPatHandle);
- PROCEDURE GDeviceChanged (gdh: GDHandle);
- FUNCTION QDDone (port:GrafPtr) : Boolean;
- _______________________________________________________________________________
-
- æKY Color…Quickdraw…Result…Codes
- æC »Result Codes Color QuickDraw
- _______________________________________________________________________________
-
- QDErr -147 Region too big
- pixmapTooDeepErr -148 PixMap record is deeper than 1 bit per pixel
- QDErr -149 Insufficient stack
- rgnTooBigErr -500 BitMap would convert into a region greater than 32 KB
- _______________________________________________________________________________
-
-
-
-
- æKY About…The…ColorQuickDraw…Chapter
- æC »ABOUT THIS CHAPTER ColorQuickDraw
- _______________________________________________________________________________
-
- Warning: This chapter has not been updated to reflect changes and improvements
- that are available on systems using 32-Bit QuickDraw. For further
- information on 32-Bit QuickDraw, please refer to the 32-Bit QuickDraw
- documentation (available on “Phil & Dave’s Excellent CD: The Release
- Version).
-
- A new version of QuickDraw has been created to take advantage of the capabilities of
- the Macintosh II. Color QuickDraw is able to use a very large number of colors and
- can take advantage of systems that have one or more screens of any size. This chapter
- describes the use of color with one screen. The following chapter, “Graphics Devices”,
- explains what your program should do to support more than one screen.
-
- The features of Color QuickDraw implemented for the Macintosh Plus, the Macintosh SE,
- and the Macintosh II are
-
- • Text drawing modes are enhanced, and now include a text mask mode,
- drawing with multibit fonts, and fractional character positioning.
- • The QuickDraw picture format (PICT) has been enhanced, and includes
- a number of new opcodes.
-
- Some of the features of Color QuickDraw for the Macintosh II are
-
- • All drawing operations supported by old QuickDraw can now be
- performed in color.
- • Color QuickDraw supports the use of as many as 2^48 colors; however,
- current hardware can only support 2^24 colors, and this assumes the
- presence of 32-Bit QuickDraw. In addition, Color QuickDraw’s color
- model is hardware-independent, allowing programs to operate
- independently of the display device.
- • Color QuickDraw includes several new data types: color tables,
- color icons, color patterns, and color cursors. These types can
- be stored as resources that are easily used by your program.
- • A new set of transfer modes has been added. These modes allow colors
- to be blended with or added to the colors that are already on the screen.
- • Most Toolbox Managers have been enhanced to use color. Thus you can
- now add color to windows, menus, controls, dialog boxes, and TextEdit
- text. Refer to the appropriate chapters for more information.
- • The QuickDraw picture format (PICT) has been extended so that Color
- QuickDraw images can be recorded in pictures.
-
- This chapter introduces the basic concepts, terminology, and data structures underlying
- the Macintosh II approach to graphics. The material presented here assumes familiarity
- with the QuickDraw concepts described in the QuickDraw chapter, such as bit maps,
- graphics ports, patterns, cursors, and transfer modes. You should also be familiar
- with the use of resources, as presented in the Resource Manager chapter.
-
- _______________________________________________________________________________
-
-
- æKY Color…Representation
- æC »COLOR REPRESENTATION ColorQuickDraw
- _______________________________________________________________________________
-
- The following sections introduce the basic concepts and terminology used in Color
- QuickDraw. It’s important to keep in mind that Color QuickDraw is designed to be
- device-independent. The range of colors available is the result of the system configuration:
- the screen resolution, the graphics hardware used to produce color, and the software
- used to select and store color values. Color QuickDraw provides a consistent way of
- dealing with color, regardless of the characteristics of the video card or display
- device.
-
- The original QuickDraw represents each dot on the screen (known as a pixel) as a
- single bit in memory. Each bit can have two values, zero or one. This allows two
- colors, usually black and white, to be displayed.
-
- To produce color graphics, more than one bit of memory per pixel displayed is needed.
- If two bits per pixel are available, four colors can be displayed. Four bits per
- pixel provides a display of 16 colors, and eight bits per pixel provides a display of
- 256 colors. The bits in a pixel, taken together, form a number known as the pixel
- value.
-
- The number of possible colors is related to the amount of memory used to store each
- pixel. Since displayed pixels are stored in RAM on the video card, rather than in the
- RAM in the Macintosh, the quality of the graphics depends on capabilities of the
- video card used.
-
- _______________________________________________________________________________
-
- »RGB Space
-
- Color QuickDraw represents colors in RGB space. Each color has a red, a green, and a
- blue component, hence the name RGB. These components may be visualized as being
- mapped into a color cube, as shown in Figures 1 and 2. (Figure 1 is a color representation
- of Figure 2.)
-
- •••Refer to Figure 1.•••
-
- Figure 1–RGB Color Cube (Color Version)
-
- •••Refer to Figure 2.•••
-
- Figure 2–RGB Color Cube (B/W Version)
-
- The data structures used within Color Quickdraw express each RGB component as an
- unsigned integer value. Each R, G, and B can have a value from $0000 to $FFFF (or 0
- to 65,535). RGB color is additive; that is, as the value of a component is increased,
- the amount of that component in the total color increases. An RGB color is black if
- all three components are set to 0, or white if each component is set to 65,535. Pixel
- values between these two extremes can be combined to represent all the possible
- colors. For instance, pixel values that lie along the diagonal between black and
- white, and for which R = G = B, are all perceived as shades of gray.
-
- _______________________________________________________________________________
-
- »Other Color Spaces
-
- In addition to RGB, several other color models are commonly used to represent colors.
- These other models include HSV (hue, saturation, value), HLS (hue, lightness, saturation),
- and CMY (cyan, magenta, yellow). If you wish to work in a different color space in
- your program, you can use the conversion routines provided in the Color Picker Package
- to convert colors to their RGB equivalents before passing them to Color QuickDraw.
- Please refer to the Color Picker Package chapter for more details.
-
- _______________________________________________________________________________
-
-
- æKY Using…Color…on…the…Macintosh…II
- æC »USING COLOR ON THE MACINTOSH II ColorQuickDraw
- _______________________________________________________________________________
-
- Before you read about the details of how to use Color QuickDraw, it’s useful to
- understand the various components of the color system and how they interact with each
- other. This section, through a series of rules and examples, attempts to illustrate
- these interactions.
-
- Rule 1: The user selects the depth of the screen using the Control Panel.
-
- This rule is mentioned first to convey the fundamental need for device independence.
- Your application shouldn’t change the depth of the screen, because it must avoid
- conflicts with desk accessories or other applications that are using the screen at
- the same time. Let the user decide how many colors should be displayed.
-
- Rule 2: Work with colors in RGB space, not with the colors on the screen.
-
- Whenever possible, your application should assume that it’s drawing to a screen that
- has 2^48 colors. Let Color QuickDraw determine what colors to actually display on the
- screen. This lets your program work better when drawing to devices that support more
- colors.
-
- The easiest way to follow this rule is for a program to call the Color Picker Package
- to select colors. The Color Picker returns an RGB value, which can then be used as
- the current color. When Color QuickDraw draws using that color, it selects the color
- that best matches the specified RGB.
-
- Rule 3: To ensure good color matching, and to avoid conflict with other applications
- and desk accessories, use the Palette Manager.
-
- If your program requires a very specific set of colors not found in the default
- selection of colors, for instance 128 levels of gray, then you should use the Palette
- Manager. The Palette Manager lets you specify the set of colors that is to be used by
- a particular window. When that window is brought to the front, its set of colors is
- switched in (with a minimal amount of impact on the rest of the screen).
-
- You should also use the Palette Manager if your application needs to animate colors
- (that is, to change the colors of pixels that are already displayed).
-
- The Palette Manager is a powerful tool because it makes sure that your application
- gets the best selection of colors across multiple screen devices and multiple screen
- depths. You don’t have to worry about interactions with desk accessories or other
- applications. Please refer to the chapter on the Palette Manager for more information
- on using the Palette Manager routines.
-
- Rule 4: Be aware that systems may have multiple video devices.
-
- Since the Macintosh II is able to support multiple screen devices, make sure your
- application takes into account the variable-sized desktop. For instance, a document
- may have been dragged to an alternate screen on one system, and then copied and used
- on another system. You should leave the document positioned where it is if it lies
- within the desktop, but move it to the main screen if it doesn’t. Please refer to the
- Graphics Devices chapter for more details.
-
- Figure 3 helps to illustrate the relationships between the various parts of the color
- system.
-
- •••Refer to Figure 3.•••
-
- Figure 3–The Macintosh II Color System
-
- _______________________________________________________________________________
-
- »From Color to Pixel
-
- To help illustrate the interconnections of the color system, let’s examine the steps
- from the specification of a color to the display of that color on the screen. This is
- an oversimplified explanation that you should use for conceptual understanding only.
-
- First, you specify the color that you want to display. Color QuickDraw stores the RGB
- components so that it knows the exact color that you specified. Let’s assume that the
- screen is set to eight bits per pixel. This means that each pixel is able to have
- 2^8, or 256, different values. Associated with the screen is a structure called a
- color table, which is a list of all the colors that the screen is currently able to
- display. So in this case the color table has 256 RGB values in it, one for each
- possible pixel value. The first entry in the color table specifies the color of all
- pixels that have value 0, the second entry specifies the color of pixels that have
- value 1, and so on. Thus the color’s position in the table determines the pixel value
- that produces that color.
-
- When you use Color QuickDraw to draw something, it retrieves the stored RGB, and asks
- the Color Manager to return the pixel value that best represents that color. The
- Color Manager effectively searches through the color table for the RGB that most
- closely matches your color. The position in the table of the best match determines
- the pixel value to be placed on the screen. Color QuickDraw then places that pixel
- value on the screen.
-
- But how does this pixel cause the assigned color to be displayed? Color QuickDraw has
- placed this pixel into the RAM on the video card. While your Macintosh II is turned
- on, the video card is continuously redisplaying every pixel that is stored in its RAM
- (very, very quickly). Internal to the video card is another color table, the Color
- Look-Up Table (CLUT). It is organized exactly like the first one, but is used the
- other way around. The video card takes the pixel value and uses it to determine what
- RGB value that pixel represents. It then uses that RGB to send off three signals
- (red, green, and blue) to the video monitor, indicating exactly what color the current
- pixel should be.
-
- Some video cards allow you to change the set of colors displayed at a given time.
- Although this is normally done transparently through the Palette Manager, it actually
- happens when both the screen’s color table and the one that is internal to the video
- card are changed to reflect the new set of colors.
-
- A very slight variation of this is used to support the monochrome mode that you can
- set from the control panel. When you set monochrome mode, the screen’s color table
- doesn’t change: from the application’s point of view, the same set of colors is still
- available. Instead, when the video card is told to use monochrome mode, it replaces
- each entry in the video card’s internal color table with a level of gray (R=G=B) that
- matches the luminance of the color it is replacing. Because of this, the switch
- between color and monochrome modes has no effect on a running program.
-
- _______________________________________________________________________________
-
-
- æKY About…Color…QuickDraw
- æC »ABOUT COLOR QUICKDRAW ColorQuickDraw
- _______________________________________________________________________________
-
- The most fundamental difference between the original QuickDraw and Color QuickDraw is
- the environment in which drawing takes place. In the original QuickDraw, all drawing
- is performed in a grafPort, the structure that defines the coordinate system, drawing
- pattern, background pattern, pen size and location, character font and style, and bit
- map in which drawing takes place. In Color QuickDraw, drawing takes place in a color
- grafPort (cGrafPort) instead. As described in later sections, most of the fields in a
- cGrafPort are the same as fields in a grafPort; however, a few fields have been
- changed to hold color information.
-
- When you’re using a grafPort in your application, you can specify up to eight colors.
- When drawing to a color screen or printing, these colors will actually be displayed.
- When drawing to an offscreen bitmap, the colors will be lost
- (since an offscreen bitmap only has one bit for each pixel).
-
- When you’re using a cGrafPort, however, you can specify up to 2^48 colors. The number
- of colors that are displayed depends on the setting of the screen, the capability of
- the printer, or the depth of the offscreen pixmap. There is more information about
- offscreen pixmaps in the “Drawing to Offscreen Devices” section of the next chapter.
-
- Color grafPorts are used by the system in the same way as grafPorts. They are the
- same size as grafPorts, and they are the structures upon which a program builds color
- windows. As with a grafPort, you set thePort to be a cGrafPort using the SetPort
- command.
-
- You can use all old drawing commands when drawing into a cGrafPort, and you can use
- all new drawing commands when drawing into a grafPort. However, since new drawing
- commands that are used in a grafPort don’t take advantage of any of the features of
- Color QuickDraw, it’s not recommended.
-
- _______________________________________________________________________________
-
- »Drawing Color in a GrafPort
-
- Although the QuickDraw graphics routines were designed mainly for monochrome drawing,
- they also included some rudimentary color capabilities. A pair of fields in the
- grafPort record, fgColor and bkColor, allow a foreground and background color to be
- specified. The color values used in these fields are based on a planar model: each
- bit position corresponds to a different color plane, and the value of each bit indicates
- whether a particular color plane should be activated. (The term color plane refers to
- a logical plane, rather than a physical plane.) The individual color planes combine
- to produce the
- full-color image.
-
- The standard QuickDraw color values consist of one bit for normal monochrome drawing
- (black on white), one bit for inverted monochrome (white on black), three bits for
- the additive primary colors (red, green, blue) used in video display, and four bits
- for the subtractive primary colors (cyan, magenta, yellow, black) used in hardcopy
- printing. The original QuickDraw interface includes a set of predefined constants for
- the standard colors:
-
- CONST
- blackColor = 33;
- whiteColor = 30;
- redColor = 209;
- greenColor = 329;
- blueColor = 389;
- cyanColor = 269;
- magentaColor = 149;
- yellowColor = 89;
-
- These are the only colors available in the original QuickDraw. All programs that draw
- into grafPorts are limited to these eight colors. When these colors are drawn to the
- screen on the Macintosh II, Color QuickDraw automatically draws them in color, if the
- screen is set to a color mode.
-
- _______________________________________________________________________________
-
- »Drawing Color in a CGrafPort
-
- Color QuickDraw represents color using the RGBColor record type, which specifies the
- red, blue, and green components of the color. Three 16-bit unsigned integers give the
- intensity values for the three additive primary colors:
-
- TYPE
- RGBColor = RECORD
- red: INTEGER; {red component}
- green: INTEGER; {green component}
- blue: INTEGER {blue component}
- END;
-
- A color of this form is referred to as an RGB value and is the form in which an
- application specifies the colors it needs. The translation from the RGB value to the
- pixel value is performed at the time the color is drawn. At times the pixel value is
- stored in the fgColor or bkColor fields. Refer to the Graphics Devices chapter for
- more details.
-
- When drawing is actually performed, QuickDraw calls the Color Manager to supply the
- color that most closely matches the requested color for the current device. As described
- in the Color Manager chapter, you can replace the method used for color matching if
- necessary. Normally pixel values are handled entirely by Color QuickDraw and the
- Color Manager; applications only refer to colors as RGB values.
-
- A set of colors is grouped into a structure called a color table:
-
- TYPE
- CTabHandle = ^CTabPtr;
- CTabPtr = ^ColorTable;
- ColorTable = RECORD
- ctSeed: LONGINT; {unique identifier from table}
- ctFlags: INTEGER; {contains flags describing the }
- { specArray; clear for a pixMap}
- ctSize: INTEGER; {number of entries -1 }
- { in ctTable}
- ctTable: cSpecArray
- END;
-
- The fields of a color table are fully described in the Color Manager chapter. The
- ctFlags field contains flags that differentiate between a device color table and an
- image color table. The ctTable field is composed of a cSpecArray, which contains an
- array of ColorSpec entries. Notice that each entry in the color table is a ColorSpec,
- not simply an RGBColor. The type ColorSpec is composed of a value field and an RGB
- value, as shown below.
-
- TYPE
- cSpecArray : ARRAY [0..0] of ColorSpec;
- ColorSpec = RECORD
- value: INTEGER; {pixel value}
- rgb: RGBColor {RGB value}
- END;
-
- Color tables are used to represent the set of colors that a device is capable of
- displaying, and they are used to describe the desired colors in an image. If the
- color table describes an image’s colors, then a ColorSpec determines the desired RGB
- for the pixel value stored in the value field. This is the most common usage, and
- most of the routines described in this chapter work with a ColorSpec in this manner.
-
- If the color table describes a device’s colors, then the value field in a ColorSpec
- is reserved for use by the Color Manager. In most cases your application won’t change
- the device color table. If you want to know more about the device color table, refer
- to the Color Manager chapter for more details.
-
- _______________________________________________________________________________
-
-
- æKY The…Color…Graphics…Port
- æC »THE COLOR GRAPHICS PORT ColorQuickDraw
- _______________________________________________________________________________
-
- As described above, programs designed to take advantage of the more powerful new
- color facilities available on the Macintosh II must use a new form of graphics port,
- the color graphics port (type cGrafPort). Color grafPorts will generally be created
- indirectly, as a result of opening a color window with the new routines NewCWindow,
- GetNewCWindow, and NewCDialog.
-
- In addition, the old routines GetNewWindow, GetNewDialog, Alert, StopAlert, NoteAlert,
- and CautionAlert will open a color grafPort if certain resources
- (types 'wctb', 'dctb', or 'actb') are present. Refer to the chapters on the Window
- and Dialog Managers for more details.
-
- The new cGrafPort structure is the same size as the old-style grafPort and most of
- its fields are unchanged. The old portBits field, which formerly held a complete
- 14-byte BitMap record embedded within the grafPort, has been replaced by a 4-byte
- PixMapHandle (portPixMap), freeing 10 bytes for other uses. (In particular, the new
- portVersion field, in the position previously occupied by the bit map’s rowBytes
- field, always has its two high
-
- bits set; these bits are used to distinguish cGrafPorts from grafPorts, in which the
- two high bits of rowBytes are always clear. See Figure 4.) Similarly, the old bkPat,
- pnPat, and fillPat fields, which previously held 8-byte patterns, have been replaced
- by three 4-byte handles. The resulting 12 bytes of additional space are taken up by
- two 6-byte RGBColor records.
-
- The structure of the color graphics port is as follows:
-
- CGrafPtr = ^CGrafPort;
- CGrafPort = RECORD
- device: INTEGER; {device ID for font }
- { selection}
- portPixMap: PixMapHandle; {port's pixel map}
- portVersion: INTEGER; {highest 2 bits always }
- { set}
- grafVars: Handle; {handle to more fields}
- chExtra: INTEGER; {extra characters}
- pnLocHFrac: INTEGER; {pen fraction}
- portRect: Rect; {port rectangle}
- visRgn: RgnHandle; {visible region}
- clipRgn: RgnHandle; {clipping region}
- bkPixPat: PixPatHandle; {background pattern}
- rgbFgColor: RGBColor; {requested foreground }
- { color}
- rgbBkColor: RGBColor; {requested background }
- { color}
- pnLoc: Point; {pen location}
- pnSize: Point; {pen size}
- pnMode: INTEGER; {pen transfer mode}
- pnPixPat: PixPatHandle; {pen pattern}
- fillPixPat: PixPatHandle; {fill pattern}
- pnVis: INTEGER; {pen visibility}
- txFont: INTEGER; {font number for text}
- txFace: Style; {text's character style}
- txMode: INTEGER; {text's transfer mode}
- txSize: INTEGER; {font size for text}
- spExtra: Fixed; {extra space}
- fgColor: LONGINT; {actual foreground color}
- bkColor: LONGINT; {actual background color}
- colrBit: INTEGER; {plane being drawn}
- patStretch: INTEGER; {used internally}
- picSave: Handle; {picture being saved}
- rgnSave: Handle; {region being saved}
- polySave: Handle; {polygon being saved}
- grafProcs: CQDProcsPtr {low-level drawing }
- { routines}
- END;
-
- Field descriptions
-
- portPixMap The portPixMap field contains a handle to the port’s pixel
- map. This is the structure that describes the cGrafPort’s pixels.
-
- portVersion The two high bits of the portVersion field are always set.
- This allows Color QuickDraw to tell the difference between a
- grafPort and a cGrafPort. The remainder of the field gives
- the version number of Color QuickDraw that created this port.
- (Initial release is version 0.)
-
- grafVars The grafVars field contains a handle to additional fields.
-
- chExtra The chExtra field is used in proportional spacing. It specifies
- a fixed point number by which to widen every character,
- excluding the space character, in a line of text. (The number
- is in 4.12 fractional notation: four bits of signed integer
- followed by 12 bits of fraction. This number is multiplied by
- txSize before it is used.) Default chExtra is 0.
-
- pnLocHFrac The pnLocHFrac field contains the fractional horizontal pen
- position used when drawing text. The initial pen fraction is 1/2.
-
- bkPixPat The bkPixPat field contains a handle to the background pixel
- pattern.
-
- rgbFgColor The rgbFgColor field contains the requested foreground color.
-
- rgbBkColor The rgbBkColor field contains the requested background color.
-
- pnPixPat The pnPixPat field contains a handle to the pixel pattern for
- pen drawing.
-
- fillPixPat The fillPixPat field contains a handle to the pixel pattern for
- area fill; for internal use only. Notice that this is not in
- the same location as old fillPat.
-
- fgColor The fgColor field contains the pixel value of the foreground
- color supplied by the Color Manager. This is the best available
- approximation to rgbFgColor.
-
- bkColor The bkColor field contains the pixel value of the background
- color supplied by the Color Manager. This is the best available
- approximation to rgbBkColor.
-
- colrBit The colrBit field is reserved: not for use by applications.
-
- grafProc The grafProc field used with a cGrafPort contains a CQDProcsPtr,
- instead of the QDProcsPtr used with a grafPort.
-
- All remaining fields have the same meanings as in the old-style grafPort.
-
- •••Refer to Figure 4.•••
-
- Figure 4–Color QuickDraw Fields
- _______________________________________________________________________________
-
- »Pixel Images
-
- The representation of a color image in memory is a pixel image, analogous to the bit
- image used by the original QuickDraw. The number of bits per pixel is called the
- depth of the image; a pixel image one bit deep is equivalent to a bit image. On the
- Macintosh II, the pixel image that appears on a video screen is normally stored on a
- graphics card rather than in main memory. To increase speed, your program can build
- additional images in RAM for rapid transfer to the display device. This technique,
- called drawing to an offscreen bitmap, is described in the Graphics Devices chapter.
-
- There are several possible arrangements of a pixel image in memory. The size and
- structure of a pixel image is described by the pixel map data structure; this structure
- and its various forms are discussed below. See Figure 5 for a representation of a
- pixel image on a system with screen depth set to eight.
-
- _______________________________________________________________________________
-
- »Pixel Maps
-
- Just as the original QuickDraw does all of its drawing in a bit map, Color QuickDraw
- uses an extended data structure called a pixel map (pixMap). In addition to the
- dimensions and contents of a pixel image, the pixel map also includes information on
- the image’s storage format, depth, resolution, and color usage:
-
- TYPE
- PixMapHandle = ^PixMapPtr;
- PixMapPtr = ^PixMap;
- PixMap = RECORD
- baseAddr: Ptr; {pointer to pixMap data}
- rowBytes: INTEGER; {offset to next row}
- bounds: Rect; {boundary rectangle}
- pmVersion: INTEGER; {color QuickDraw version }
- { number}
- packType: INTEGER; {packing format}
- packSize: LONGINT; {size of data in packed }
- { state}
- hRes: Fixed; {horizontal resolution}
- vRes: Fixed; {vertical resolution}
- pixelType: INTEGER; {format of pixel image}
- pixelSize: INTEGER; {physical bits per pixel}
- cmpCount: INTEGER; {logical components per }
- { pixel}
- cmpSize: INTEGER; {logical bits per component}
- planeBytes: LONGINT; {offset to next plane}
- pmTable: CTabHandle; {absolute colors for this }
- { image}
- pmReserved: LONGINT {reserved for future }
- { expansion}
- END;
-
- Field descriptions
-
- baseAddr The baseAddr field contains a pointer to first byte of the
- pixel image, the same as in a bitMap. For optimal performance
- this should be a multiple of four.
-
- rowBytes The rowBytes field contains the offset in bytes from one row of
- the image to the next, the same as in a bitMap. As before,
- rowBytes must be even. The high three bits of rowBytes are used
- as flags. If bit 15 = 1, the data structure is a pixMap;
- otherwise it is a bitMap. Bits 14 and 13 are not used and must
- be 0.
-
- bounds The bounds field is the boundary rectangle, which defines the
- coordinate system and extent of the pixel map; it’s similar to
- a bitMap. This rectangle is in pixels, so depth has no effect
- on its values.
-
- pmVersion The pmVersion is the version number of Color QuickDraw that
- created this pixel map, which is provided for future
- compatibility. (Initial release is version 0.)
-
- packType The packType field identifies the packing algorithm used to
- compress image data. Color QuickDraw currently supports only
- packType = 0, which means no packing.
-
- packSize The packSize field contains the size of the packed image in
- bytes. When packType = 0, this field should be set to 0.
-
- hRes The hRes is the horizontal resolution of pixMap data in pixels
- per inch.
-
- vRes The vRes is the vertical resolution of pixMap data in pixels
- per inch. By default, hRes = vRes = 72 pixels per inch.
-
- pixelType The pixelType field specifies the storage format for a pixel
- image. 0 = chunky, 1 = chunky/planar, 2 = planar. Only chunky
- is used in the Macintosh II.
-
- pixelSize The pixelSize is the physical bits per pixel; it’s always a
- power of 2.
-
- cmpCount The cmpCount is the number of color components per pixel. For
- chunky pixel images, this is always 1.
-
- cmpSize The cmpSize field contains the logical bits per RGBColor
- component. Note that (cmpCount*cmpSize) doesn’t necessarily
- equal pixelSize. For chunky pixel images, cmpSize = pixelSize.
-
- planeBytes The planeBytes field is the offset in bytes from one plane to
- the next. If only one plane is used, as is the case with chunky
- pixel images, this field is set to 0.
-
- pmTable The pmTable field is a handle to table of colors used in the
- pixMap. This may be a device color table or an image color table.
-
- pmReserved The pmReserved field is reserved for future expansion; it must
- be set to 0 for future compatibility.
-
- The data in a pixel image can be organized several ways, depending on the characteristics
- of the device or image. The pixMap data structure supports three pixel image formats:
- chunky, planar, and chunky/planar.
-
- In a chunky pixel image, all of a pixel’s bits are stored consecutively in memory,
- all of a row’s pixels are stored consecutively, and rowBytes indicates the offset in
- memory from one row to the next. This is the only one of the three formats that’s
- supported by this implementation of Color QuickDraw. The pixel depths that are currently
- supported are 1, 2, 4, and 8 bits per pixel. In a chunky pixMap cmpCount = 1 and
- cmpSize = pixelSize. Figure 5 shows a chunky pixel image for a system with screen
- depth set to eight.
-
- A planar pixel image is a pixel image separated into distinct bit images in memory,
- one for each color plane. Within the bit image, rowBytes indicates the offset in
- memory from one row to the next. PlaneBytes indicates the offset in memory from one
- plane to the next. The planar format isn’t supported by this implementation of Color
- QuickDraw.
-
- A chunky/planar pixel image is separated into distinct pixel images in memory, typically
- one for each color component. Within the pixel image, rowBytes indicates the offset
- in memory from one row to the next. PlaneBytes indicates the offset in memory from
- one plane to the next. The chunky/planar format isn’t supported by this implementation
- of Color QuickDraw.
-
- •••Refer to Figure 5.•••
-
- Figure 5–A Pixel Image
-
- _______________________________________________________________________________
-
- »Pixel Patterns
-
- With Color QuickDraw, monochrome patterns are replaced by a new form of pattern
- structure, the pixel pattern, which offers greater flexibility in the use of color.
- The three pattern fields in a grafPort—pnPat, bkPat, and fillPat—have been replaced
- by the pnPixPat, bkPixPat, and fillPixPat fields in a cGrafPort. The format for a
- pixel pattern is shown below:
-
- TYPE
- PixPatHandle = ^PixPatPtr;
- PixPatPtr = ^PixPat;
- PixPat = RECORD
- patType: INTEGER; {pattern type}
- patMap: PixMapHandle; {pattern characteristics}
- patData: Handle; {pixel image defining }
- { pattern}
- patXData: Handle; {expanded pixel image}
- patXValid: INTEGER; {flags for expanded }
- { pattern data}
- patXMap: Handle; {handle to expanded }
- { pattern data}
- pat1Data: Pattern; {old-style pattern/RGB }
- { color}
- END;
-
- Field descriptions
-
- patType The patType field specifies the pattern’s type. The possible
- values include: 0 = old-style pattern, 1 = full-color pixel
- pattern, 2 = RGB pattern.
-
- patMap The patMap field is a handle to the pixel map describing the
- pattern’s pixel image.
-
- patData The patData field is a handle to the pattern’s pixel image.
-
- patXData The patXData field is a handle to an expanded pixel image used
- internally by Color QuickDraw.
-
- patXValid When the pattern’s data or color table change, you can
- invalidate the expanded data by setting the patXValid field to –1.
-
- patXMap The patXMap field is a handle that is reserved for use by Color
- QuickDraw.
-
- pat1Data The pat1Data field contains an old-style 8-by-8 pattern to be
- used when this pattern is drawn into old grafPort. NewPixPat
- sets this field to 50% gray.
-
- Old-style patterns are still supported. When used in a cGrafPort, the QuickDraw
- routines PenPat and BackPat store the pattern within pnPixPat and bkPixPat, respectively,
- and set the patType to 0 to indicate that the structure contains old pattern data.
- Such patterns are limited to the original 8-by-8 dimensions and are always drawn
- using the values in the cGrafPort’s rgbFgColor and rgbBkColor fields. Similarly,
- filled drawing operations, such as FillRect, are also supported.
-
- In a pixel pattern (patType = 1), the pattern’s dimensions, depth, resolution
- (only 72 pixels per inch is supported), set of colors, and other characteristics are
- defined by a pixel map, referenced by the patMap handle. Since the pixel map has its
- own color table, pixel patterns can consist of any number of colors, and don’t usually
- use the foreground and background colors. The section on relative patterns, below,
- describes an exception to this rule.
-
- Furthermore, patType = 1 patterns are not limited to a fixed size: their height and
- width can be any power of 2, as specified by the height and width of
- patMap^^.bounds. (Notice that a pattern eight bits wide—the original QuickDraw size—has
- a row width of just one byte, contrary to the usual rule that the rowBytes field must
- be even.) This pattern type is generally read into memory using the GetPixPat routine,
- or set using the PenPixPat or BackPixPat routines.
-
- Although the patMap defines the pattern’s characteristics, its baseAddr field is
- ignored; for a type1 pattern, the actual pixel image defining the pattern is stored
- in the handle in the pattern’s patData field. The pattern’s depth need not match that
- of the pixel map it’s painted into; the depth will be adjusted automatically when the
- pattern is drawn. Color QuickDraw maintains a private copy of the pattern’s pixel
- image, expanded to the current screen depth, and aligned to the current grafPort or
- cGrafPort, in the patXData field.
-
- The third pattern type is RGBPat (patType = 2). Using the MakeRGBPat routine, the
- application can specify the exact color it wants to use. QuickDraw selects a pattern
- to approximate that color. In this way, an application can effectively increase the
- color resolution of the screen. Pixel patterns are particularly useful for dithering:
- mixing existing colors together to create the illusion of a third color that’s unavailable
- on a particular device. The MakeRGBPat routine aids in this process by constructing a
- dithered pattern to approximate a given absolute color. (See the description of
- MakeRGBPat in the
- “Color QuickDraw Routines” section for more details.) In the current implementation
- of Color QuickDraw, an RGBPat can display 125 different patterns on a 4-bit-deep
- screen, or 2197 different patterns on an 8-bit-deep screen.
-
- For an RGBPat, the RGB defines the image; there is no image data. An RGBPat has an
- 8-by-8, 2-bit-deep pattern.
-
- A program that creates a pixMap must initialize the pixMap’s color table to describe
- the pixels. GetCTable could be used to read such a table from a resource file; you
- could then dispose of the pixMap’s color table and replace it with the one returned
- by GetCTable.
-
- »Relative Patterns
-
- Type1 pixel patterns contain color tables that describe the colors they use. Generally
- such a color table contains one entry for each color used in the pattern. For instance,
- if your pattern has five colors in it, you would probably create a four-bit-per-pixel
- pattern that uses pixel values 0–4, and a color table with five entries, numbered
- 0–4, that contain the RGB specifications for those pixel values.
-
- When the pattern is drawn, each possible pixel value that isn’t specified in the
- color table is assigned a color. The largest unassigned pixel value becomes the
- foreground color; the smallest unassigned pixel value is assigned the background
- color. Remaining unassigned pixel values are given colors that are evenly distributed
- between the foreground and background.
-
- For instance, in the color table mentioned above, pixel values 5–15 are unused.
- Assume that the foreground color is black and the background color is white. Pixel
- value 15 is assigned the foreground color, black; pixel value 5 is assigned the
- background color, white; the nine pixel values between them are assigned evenly
- distributed shades of gray. If the pixMap’s color table is set to NIL, all pixel
- values are determined by blending the foreground and background colors.
-
- _______________________________________________________________________________
-
- »Transfer Modes
-
- A transfer mode is a method of placing information on the display devices. It involves
- an interaction between what your application is drawing (the source) and what’s
- already there (the destination). The original QuickDraw offered eight basic transfer
- modes:
-
- • completely replacing the destination with the source (Copy), and its
- inverse (NotCopy)
- • combining the destination with the source (Or), and its inverse (NotOr)
- • selectively clearing the destination with the source (Bic, for “bit
- clear”), and its inverse (NotBic)
- • selectively inverting the destination with the source (Xor), and its
- inverse (NotXor)
-
- This is how color affects these eight transfer modes when the source pixels are
- either black (all 1’s) or white (all 0’s):
-
- Copy The Copy mode applies the foreground color to the black part of
- the source (the part containing 1’s) and the background color to
- the white part of the source (the part containing 0’s), and
- replaces the destination with the colored source.
-
- NotCopy The NotCopy mode applies the foreground color to the white part
- of the source and the background color to the black part of the
- source, and replaces the destination with the colored source. It
- thus has the effect of reversing the foreground and background
- colors.
-
- Or The Or mode applies the foreground color to the black part of the
- source and replaces the destination with the colored source. The
- white part of the source isn’t transferred to the destination. If
- the foreground is black, the drawing will be faster.
-
- NotOr The NotOr mode applies the foreground color to the white part of
- the source and replaces the destination with the colored source.
- The black part of the source isn’t transferred to the destination.
- If the foreground is black, the drawing will be faster.
-
- Bic The Bic mode applies the background color to the black part of
- the source and replaces the destination with the colored source.
- The white part of the source isn’t transferred to the destination.
-
- NotBic The NotBic mode applies the background color to the white part
- of the source and replaces the destination with the colored source.
- The black part of the source isn’t transferred to the destination.
-
- Xor The Xor mode complements the bits in the destination corresponding
- to the bits equal to 1 in the source. When used on a colored
- destination, the color of the inverted destination isn’t defined.
-
- NotXor The NotXor mode inverts the bits that are 0 in the source. When
- used on a colored destination, the color of the inverted
- destination isn’t defined.
-
- Pixels of colors other than black and white aren’t all 1’s or all 0’s, so the application
- of a foreground color or a background color to the pixel produces an undefined result.
- For this reason, and because a pixPat already contains color, the foreground and
- background colors are ignored when your application is drawing with a pixPat. When
- your program draws a pixMap the foreground and background colors are not ignored.
- Make sure that the foreground is black and the background is white before you call
- CopyBits or the result will be undefined.
-
- If you intend to draw with pixMaps or pixPats, you will probably want to use the Copy
- mode or one of the arithmetic modes described in the following section.
-
- To help make color work well on different screen depths, Color QuickDraw does some
- validity checking of the foreground and background colors. If your application is
- drawing to a cGrafPort with a depth equal to 1 or 2, and if the RGB values of the
- foreground and background colors aren’t the same, but both of them map to the same
- pixel value, then the foreground color is inverted. This ensures that, for instance,
- red text drawn on a green background doesn’t map to black on black.
-
- _______________________________________________________________________________
-
- »Arithmetic Drawing Modes
-
- Color QuickDraw uses a set of arithmetic drawing modes designed specifically for use
- with color. These modes change the destination pixels by performing arithmetic operations
- on the source and destination pixels. These drawing modes are most useful in 8-bit
- color, but work on 4-bit and 2-bit color as well. If the destination bitmap is one
- bit deep, the mode reverts to one of the old transfer modes that approximates the
- arithmetic mode requested.
-
- Each drawing routine converts the source and destination pixels to their RGB components,
- performs an operation on each pair of components to provide a new RGB value for the
- destination, and then assigns the destination a pixel value close to the calculated
- RGB value. The arithmetic modes listed below can be used for all drawing operations;
- your application can pass them as a parameter to TextMode, PenMode, or CopyBits.
-
- addOver This mode assigns to the destination pixel the color closest to
- the sum of the source and destination RGB values. If the sum of
- any of the RGB components exceeds the maximum allowable value,
- 65,535, the RGB value wraps around to the value less 65,536.
- AddOver is slightly faster than addPin. If the destination bitmap
- is one bit deep, addOver reverts to Xor.
-
- addPin This mode assigns to the destination pixel the color closest to
- the sum of the destination RGB values, pinned to a maximum allowable
- RGB value. For grafPorts, the pin value is always white. For
- cGrafPorts, the pin value is assigned using OpColor. If the
- destination bitmap is one bit deep, addPin reverts to Bic.
-
- subOver This mode assigns to the destination pixel the color closest to
- the difference of the source and destination RGB values. If the
- result is less than 0, the RGB value wraps around to 65,536 less
- the result. SubOver is slightly faster than subPin. If the
- destination bitmap is one bit deep, subOver reverts to Xor.
-
- subPin This mode assigns to the destination pixel the color closest to
- the difference of the sum and the destination RGB values, pinned
- to a minimum allowable RGB value. For grafPorts, the pin value is
- always black. In a cGrafPort, the pin value is assigned by using
- OpColor. If the destination bitmap is one bit deep, subPin reverts
- to Or.
-
- adMax (Arithmetic Drawing Max) This mode compares the source and
- destination pixels, and replaces the destination pixel with the
- color containing the greater saturation of each of the RGB
- components. Each RGB component comparison is done independently,
- so the resulting color isn’t necessarily either the source or the
- destination color. If the destination bitmap is one bit deep,
- adMax reverts to Bic.
-
- adMin (Arithmetic Drawing Min) This mode compares the source and
- destination pixels, and replaces the destination pixel with
- the color containing the lesser saturation of each of the RGB
- components. Each RGB component is compared independently, so
- the resulting color isn’t necessarily the source or the
- destination color. If the destination bitmap is one bit deep,
- adMin reverts to Or.
-
- blend This mode replaces the destination pixel with a weighted average
- of the colors of the source and destination pixels. The formula
- used to calculate the destination is:
-
- dest = source*weight/65,536 + destination*(1-weight/65,536)
-
- where weight is an unsigned value between 1 and 65,535. In a
- grafPort, the weight is set to 50% gray, so that equal weights
- of the source and destination RGB components are combined to
- produce the destination color. In a cGrafPort, the weight is an
- RGBColor that individually specifies the weights of the red,
- green, and blue components. The weight is assigned using OpColor.
- If the destination bitmap is one bit deep, blend reverts to Copy.
-
- Because drawing with the arithmetic modes uses the closest matching pixel values, and
- not necessarily exact matches, these modes might not produce the results you expect.
- For instance, suppose srcCopy mode is used to paint a green pixel on the screen in
- 4-bit mode. Of the 16 colors available, the closest green may contain a small amount
- of red, as in RGB components of 300 red, 65,535 green, and 0 blue. AddOver is then
- used to paint a red pixel on top of the green pixel, ideally resulting in a yellow
- pixel. The red pixel’s RGB components are 65,535 red, 0 green, and 0 blue. Adding the
- red components together wraps to 300, since the largest representable value is 65,535.
- In this case, AddOver would cause no visible change at all. Using AddPin with an
- opColor of white would produce the desired results.
-
- On the Macintosh II the rules for setting the pen mode and the text mode have been
- relaxed slightly. It’s no longer necessary to specify a pattern mode or a source mode
- (patCopy as opposed to srcCopy) to perform a particular operation. QuickDraw will
- choose the correct drawing mode automatically. However, to be compatible with earlier
- versions of QuickDraw, you application must specify the correct drawing mode. Text
- and bitmaps should always use a source mode; rectangles, regions, polygons, arcs,
- ovals, round rectangles, and lines should always use a pattern mode.
-
- The constants used for the arithmetic transfer modes are as follows:
-
- CONST
- blend = 32;
- addPin = 33;
- addOver = 34;
- subPin = 35;
- adMax = 37;
- subOver = 38;
- adMin = 39;
-
- Warning: Unlike the rest of QuickDraw, the arithmetic modes don’t call the
- Color Manager when mapping a requested RGB value to a pixel value.
- If your application replaces the color matching routines, you must
- either not use these modes, or you must maintain the inverse table
- using the Color Manager routines.
-
- _______________________________________________________________________________
-
- »Replace with Transparency
-
- The transparent mode replaces the destination pixel with the source pixel if the
- source pixel isn’t equal to the background color. This mode is most useful in 8-bit,
- 4-bit, or 2-bit color modes. To specify a transparent pattern, use the drawing mode
- transparent+patCopy. If the destination pixMap is one bit deep, the mode is translated
- to Or. Transparency can be specified as a parameter to TextMode, PenMode, or CopyBits.
-
- Transparent mode is optimized to handle source bitmaps with large transparent holes,
- as an alternative to specifying an unusual clipping region or mask parameter to
- CopyMask. Patterns aren’t optimized, and may not draw as quickly.
-
- The constant used for transparent mode is
-
- CONST
- transparent = 36;
-
- _______________________________________________________________________________
-
- »The Hilite Mode
-
- This new method of highlighting exchanges the background color and the highlight
- color in the destination. This has the visual effect of using a highlighting pen to
- select the object. For instance, TextEdit uses the hilite mode to select text: if the
- highlight color is yellow, selected text appears on a yellow background. In general,
- highlighting should be used in place of inversion when selecting and deselecting
- objects such as text or graphics.
-
- There are two ways to use hilite mode. The easiest is to call
-
- BitClr (Ptr(HiliteMode,pHiliteBit));
-
- just before calling InvertRect, InvertRgn, InvertArc, InvertRoundRct, or InvertPoly
- or any drawing using srcXor mode. On a one-bit-deep destination, this will work
- exactly like inversion, and is compatible with all versions of QuickDraw. Color
- QuickDraw resets the hilite bit after performing each drawing operation, so the
- hilite bit should be cleared immediately before calling a routine that is to do
- highlighting. Routines that formerly used Xor inversion, such as the Invert routines,
- Paint, Frame, LineTo, text drawing, and CopyBits, will now use hilite mode if the
- hilite bit is clear.
-
- Assembly language note: You can use
-
- BCLR #hiliteBit, hiliteMode
-
- Do not alter the other bits in HiliteMode.
-
- The second way to use hilite mode is to pass it directly to TextMode, PenMode, or
- CopyBits as a parameter.
-
- Hilite mode uses the source or pattern to decide which bits to exchange; only bits
- that are on in the source or pattern can be highlighted in the destination.
-
- A very small inversion should probably not use hilite mode, because a small selection
- in the hilite color might be too hard to see. TextEdit, for instance, uses hilite
- mode to select and deselect text, but not to blink the insertion point.
-
- Hilite mode is optimized to look for consecutive pixels in either the hilite or
- background colors. For example, if the source is an all black pattern, the highlighting
- will be especially fast, operating internally on a long word at a time instead of a
- pixel at a time. Highlighting a large area without such consecutive pixels (a gray
- pattern, for instance) can be slow.
-
- The global variable HiliteRGB is read from parameter RAM when the machine starts. Old
- grafPorts use the RGB values in the global HiliteRGB as the highlight color. Color
- grafPorts default to the global HiliteRGB, but can be overridden by the HiliteColor
- procedure.
-
- The constants used with hilite mode are listed below:
-
- CONST
- hilite = 50;
- pHiliteBit = 0; {this is the correct value for use when calling }
- { the BitClear trap. BClr must use the assembly }
- { language equate hiliteBit}
- _______________________________________________________________________________
-
-
- æKY The…Color…Cursor
- æC »THE COLOR CURSOR ColorQuickDraw
- _______________________________________________________________________________
-
- Color QuickDraw supports the use of color cursors. The size of a cursor is still
- 16-by-16 pixels. The new CCrsr data structure is substantially different from the
- Cursor data structure used with the original QuickDraw: the CCrsr fields crsr1Data,
- crsrMask, and crsrHotSpot are the only fields that have counterparts in the Cursor
- record.
-
- The structure of the color cursor is as follows:
-
- TYPE
- CCrsrHandle = ^CCrsrPtr;
- CCrsrPtr = ^CCrsr;
- CCrsr = RECORD
- crsrType: INTEGER; {type of cursor}
- crsrMap: PixMapHandle; {the cursor's pixmap}
- crsrData: Handle; {cursor's data}
- crsrXData: Handle; {expanded cursor data}
- crsrXValid: INTEGER; {depth of expanded data}
- crsrXHandle: Handle; {Reserved for future }
- { use}
- crsr1Data: Bits16; {one-bit cursor}
- crsrMask: Bits16; {cursor's mask}
- crsrHotSpot: Point; {cursor's hotspot}
- crsrXTable: LONGINT; {private}
- crsrID: LONGINT; {ctSeed for expanded }
- { cursor}
- END;
-
- You will not normally need to manipulate the fields of a color cursor. Your application
- can load in a color cursor using the GetCCursor routine, and display it using the
- SetCCursor routine. When the application is finished using a color cursor, it should
- dispose of it using the DisposCCursor routine. These routines are discussed below in
- the section “Color QuickDraw Routines”.
-
- Color cursors are stored in resources of type 'crsr'. The format of the 'crsr' resource
- is given in the section “Color QuickDraw Resource Formats”.
-
- Field descriptions
-
- crsrType The crsrType field specifies the type of cursor. Possible
- values are: $8000 = old cursor, $8001 = new cursor.
-
- crsrMap The crsrMap field is a handle to the pixel map defining the
- cursor’s characteristics.
-
- crsrData The crsrData field is a handle to the cursor’s pixel data.
-
- crsrXData The crsrXData field is a handle to the expanded pixel image
- used internally by Color QuickDraw (private).
-
- crsrXValid The crsrXValid field contains the depth of the expanded cursor
- image. If you change the cursor’s data or color table, you
- should set this field to 0 to cause the cursor to be reexpanded.
- You should never set it to any other values.
-
- crsrXHandle The crsrXHandle field is reserved for future use.
-
- crsr1Data The crsr1Data field contains a 16-by-16 one-bit image to be
- displayed when the cursor is on 1-bit or 2-bit per pixel screens.
-
- crsrMask The crsrMask field contains the cursor’s mask data. The same
- 1-bit-deep mask is used with crsrData and crsr1Data.
-
- crsrHotSpot The crsrHotSpot field contains the cursor’s hot spot.
-
- crsrXTable The crsrXTable field is reserved for future use.
-
- crsrID The crsrID field contains the ctSeed for the cursor.
-
- The first four fields of the CCrsr record are similar to the first four fields of the
- PixPat record, and are used in the same manner by Color QuickDraw. See the discussion
- of the patMap field under the section titled “Pixel Patterns” for more information on
- how the crsrMap is used.
-
- The display of a cursor involves a relationship between a mask, stored in the crsrMask
- field with the same format used for old cursor masks, and an image. There are two
- possible sources for a color cursor’s image. When the cursor is on a screen whose
- depth is one or two bits per pixel, the image for the cursor is taken from Crsr1Data,
- which contains old-style cursor data. In this case, the relationship between data and
- mask is exactly as before. When the screen depth is greater than two bits per pixel,
- the image for the cursor is taken from crsrMap and crsrData; the relationship between
- mask and data is described in the following paragraph.
-
- The data pixels within the mask replace the destination pixels. The data pixels
- outside the mask are displayed using an XOR with the destination pixels. If data
- pixels outside the mask are 0 (white), the destination pixels aren’t changed. If data
- pixels outside the mask are all 1’s (black), the destination pixels are complemented.
- All other values outside of the mask cause unpredictable results.
-
- To work properly, a color cursor’s image should contain white pixels
- (R = G = B = $FFFF) for the transparent part of the image, and black pixels
- (R = G = B = $0000) for the inverting part of the image, in addition to the other
- colors in the cursor’s image. Thus, to define a cursor that contains two colors, it’s
- necessary to use a 2-bit-per-pixel cursor image (that is, a four-color image).
-
- If your application changes the value of your cursor data or its color table, it
- should set the crsrXValid field to 0 to indicate that the cursor’s data needs to be
- reexpanded, and assign a new unique value to crsrID (unique values can be obtained
- using the GetCTSeed routine); then it should call SetCCursor to display the changed
- cursor.
-
- _______________________________________________________________________________
-
-
- æKY Color…Icons
- æC »COLOR ICONS ColorQuickDraw
- _______________________________________________________________________________
-
- A new data structure, known as CIcon, supports the use of color icons. The structure
- of the color icon is as follows:
-
- TYPE
- CIconHandle = ^CIconPtr;
- CIconPtr = ^CIcon;
- CIcon = RECORD
- iconPMap: PixMap; {the icon's pixMap}
- iconMask: BitMap; {the icon's mask bitmap}
- iconBMap: BitMap; {the icon's bitMap}
- iconData: Handle; {the icon's data}
- iconMaskData: ARRAY[0..0] OF INTEGER;
- {icon's mask and bitmap }
- { data}
- END;
-
- You won’t normally need to manipulate the fields of color icons. Your application can
- load a color icon into memory using the routine GetCIcon. To draw a color icon that’s
- already in memory, use PlotCIcon. When your application is through with a color icon,
- it can dispose of it using the DisposCIcon routine. These routines are discussed
- below in the section “Color QuickDraw Routines”.
-
- Color icons are stored in a resource file as resource type 'cicn'. The format of the
- 'cicn' resource is given in the section “Using Color QuickDraw
- Resources”.
-
- Field descriptions
-
- iconPMap The iconPMap field contains the pixel map describing the
- icon. Note that pixMap is inline, not a handle.
-
- iconMask The iconMask field contains a bit map for the icon’s mask.
-
- iconBMap The iconBMap field contains a bit map for the icon.
-
- iconData The iconData field contains a handle to the icon’s pixel image.
-
- iconMaskData The iconMaskData field is an array containing the icon’s mask
- data followed by the icon’s bitmap data. This is only used
- when the icon is stored as a resource.
-
- You can use color icons in menus in the same way that you could use old icons in
- menus. The menu definition procedure first tries to load in a 'cicn' with the specified
- resource ID. If it doesn’t find one, then it tries to load in an
- 'ICON' with that ID. The Dialog Manager will also use a 'cicn' in place of an
- 'ICON' if there is one with the ID specified in the item list. For more information,
- see the Menu Manager and Dialog Manager chapters.
-
- _______________________________________________________________________________
-
-
- æKY Using…Color…QuickDraw
- æC »USING COLOR QUICKDRAW ColorQuickDraw
- _______________________________________________________________________________
-
- This section gives an overview of routines that you will typically call while using
- Color QuickDraw. All routines are discussed below in the section “Color QuickDraw
- Routines”.
-
- Using a color graphics port is much like using an old-style grafPort. The old routines
- SetPort and GetPort operate on grafPorts or cGrafPorts, and the global variable
- ThePort points to either to a grafPort or a cGrafPort. Color QuickDraw examines the
- two high bits of the portBits.rowBytes field (the portVersion field in a cGrafPort).
- If these bits equal 0, then it is a grafPort; if they are both 1, then it is a cGrafPort.
- In Pascal, use type coercion to convert between GrafPtr and cGrafPtr. For example:
-
- VAR myPort: CGrafPtr;
- SetPort (GrafPtr(myPort));
-
- There’s still a graphics pen for line drawing, with a current size, location, pattern,
- and transfer mode; all of the old line- and shape-drawing operations, such as Move,
- LineTo, FrameRect, and PaintPoly, still work just as before. However, colors should
- be set with the new routines RGBForeColor and RGBBackColor (described below) instead
- of the old ForeColor and BackColor routines. If your application is using the Palette
- Manager, use the routines PMForeColor and PMBackColor instead.
-
- PenPat and BackPat are still supported, and will construct a pixel pattern equivalent
- to the specified bit pattern. The patType field of this pattern is set to 0; thus it
- will always use the port’s current foreground and background colors at the time of
- drawing.
-
- To read a multicolored pattern from a resource file, use the GetPixPat routine. Set
- these patterns using PenPixPat and BackPixPat, or pass them as parameters to Color
- QuickDraw’s color fill routines (such as FillCRect). These patterns have their own
- color tables and are generally not affected by the port’s foreground and background
- colors (refer to the earlier discussion of relative patterns).
-
- Most routines that accept bitMaps as parameters also accept pixMaps (not PixMapHandles).
- Likewise, any new routine that has a pixMap as a parameter will also accept a bitMap.
- This allows one set of routines to work for all operations on images; the high bit of
- the rowBytes field distinguishes whether the parameter is a bitMap or a pixMap.
-
- It’s worth noting here that resources are used slightly differently by Color QuickDraw
- than they were used by QuickDraw. For instance, with old QuickDraw, your application
- could call GetCursor before each SetCursor; the same handle would be passed back to
- the application each time. With Color QuickDraw, the color cursor is a compound
- structure, more complex than a simple resource handle. Color QuickDraw reads the
- requested resource, copies it, and then alters the copy before passing it to the
- application. Each time your application calls GetCCursor, it gets a new copy of the
- cursor. This means that your program should only call GetCCursor once, even if it
- does multiple SetCCursor calls. The new resource types should be marked as purgeable
- if you are concerned about memory space. This discussion holds true for color cursor,
- color pattern, color icon, and color table resources.
-
- _______________________________________________________________________________
-
-
- æKY Color…QuickDraw…Routines
- æC »COLOR QUICKDRAW ROUTINES ColorQuickDraw
- _______________________________________________________________________________
-
- Color QuickDraw continues to support all the original QuickDraw calls described in
- the QuickDraw chapter. The following sections describe in detail the new Color QuickDraw
- routines, as well as changes to existing routines.
-
- _______________________________________________________________________________
-
- »Operations on CGrafPorts
-
- PROCEDURE OpenCPort (port: CGrafPtr);
-
- The OpenCPort procedure is analogous to OpenPort, except it opens a cGrafPort instead
- of a grafPort. You will rarely need to use this call, since OpenCPort is called by
- NewCWindow and GetNewCWindow, as well as by the Dialog Manager when the appropriate
- color resources are present. OpenCPort allocates storage for all the structures in
- the cGrafPort, and then calls InitCPort to initialize them. The new structures
- allocated are the portPixMap, the pnPixPat, the fillPixPat, the bkPixPat, and the
- grafVars handle. The GrafVars record structure is shown below:
-
- TYPE
- GrafVars = RECORD
- rgbOpColor: RGBColor; {color for addPin, subPin, and }
- { blend}
- rgbHiliteColor: RGBColor; {color for highlighting}
- pmFgColor: Handle; {Palette handle for foreground }
- { color}
- pmFgIndex: INTEGER; {index value for foreground}
- pmBkColor: Handle; {Palette handle for background }
- { color}
- pmBkIndex: INTEGER; {index value for background}
- pmFlags: INTEGER; {Flags for Palette Manager}
- END;
-
- The rgbOpColor field is initialized as black, and the rgbHiliteColor field is initialized
- as the default HiliteRGB. All the rest of the GrafVars fields are initially zero.
-
- The portPixMap is not allocated a color table of its own. When InitCPort is called,
- the handle to the current device’s color table is copied into the portPixMap.
-
- PROCEDURE InitCPort (port: CGrafPtr);
-
- The InitCPort procedure does not allocate any storage. It merely initializes all the
- fields in the cGrafPort to their default values. All old fields are initialized to
- the same values as a grafPort’s fields. New fields are given the following values:
-
- portPixMap: copied from theGDevice^^.GDPMap
- portVersion: $C000
- grafVars: opColor initialized to black, rgbHiliteColor
- initialized as default HiliteRGB. All other
- fields are initialized as 0.
- chExtra: 0
- pnLocHFrac: 1/2
- bkPixPat: white
- rgbFgColor: black
- rgbBkColor: white
- pnPixPat: black
- fillPixPat: black
-
- The default portPixMap is set to be the same as the current device’s pixMap. This
- allows you to create an offscreen port that is identical to the screen’s grafPort or
- cGrafPort for drawing offscreen. If you want to use a different set of colors for
- offscreen drawing, you should create a new gDevice, and set it as the current gDevice
- before opening the cGrafPort. Refer to the section on offscreen bitMaps in the Graphics
- Devices chapter for more details.
-
- As mentioned above, InitCPort does not copy the data from the current device’s color
- table to the portPixMap’s color table. It simply replaces whatever is in the pmTable
- field with a copy of the handle to the current device’s color table.
-
- If you try to initialize a grafPort using InitCPort, it will simply return without
- doing anything.
-
- PROCEDURE CloseCPort (port: CGrafPtr);
-
- CloseCPort releases the memory allocated to the cGrafPort. It disposes of the visRgn,
- the clipRgn, the bkPixPat, the pnPixPat, the fillPixPat, and the grafVars handle. It
- also disposes of the portPixMap, but doesn’t dispose of the portPixMap’s color table
- (which is really owned by the gDevice). If you have placed your own color table into
- the portPixMap, either dispose of it before calling CloseCPort, or store another
- reference to it for other uses.
-
- _______________________________________________________________________________
-
- »Setting the Foreground and Background Colors
-
- PROCEDURE RGBForeColor (color : RGBColor);
- PROCEDURE RGBBackColor (color : RGBColor);
-
- These two calls set the foreground and background colors to the best available match
- for the current device. The only drawing operations that aren’t affected by these
- colors are PlotCIcon, and drawing using the new color patterns. Before you call
- CopyBits with a pixMap as the source, you should set the foreground to black and the
- background to white.
-
- If the current port is a cGrafPort, the specified RGB is placed in the rgbFgColor or
- rgbBkColor field (and the pixel value most closely matching that color is placed in
- the fgColor or bkColor field). If the current port is a grafPort, fgColor or bkColor
- is set to the old QuickDraw color determined by taking the high bit of each of the R,
- G, and B components, and using that three-bit number to select one of the eight
- QuickDraw colors. The ordering of the QuickDraw colors is shown in the GetForeColor
- description.
-
- PROCEDURE GetForeColor (VAR color : RGBColor);
- PROCEDURE GetBackColor (VAR color : RGBColor);
-
- These two calls return the RGB components of the foreground and background colors set
- in the current port. The calls work for both grafPorts and cGrafPorts. If the current
- port is a cGrafPort, the returned value is taken directly from the rgbFgColor or
- rgbBkColor field. If the current port is a grafPort, then only eight possible RGB
- values can be returned. These eight values are determined by the values in a global
- variable named QDColors, which is a pointer to a color table containing the current
- QuickDraw colors.
-
- The colors are stored in the following order:
-
- Value Color Red Green Blue
-
- 0 black $0000 $0000 $0000
- 1 yellow $FC00 $F37D $052F
- 2 magenta $F2D7 $0856 $84EC
- 3 red $DD6B $08C2 $06A2
- 4 cyan $0241 $AB54 $EAFF
- 5 green $0000 $8000 $11B0
- 6 blue $0000 $0000 $D400
- 7 white $FFFF $FFFF $FFFF
-
- This is the set of colors that Color QuickDraw uses to determine precisely what
- colors should be displayed by an old grafPort that is using color. The default set of
- colors has been adjusted to match the colors produced on the ImageWriter II printer.
-
- _______________________________________________________________________________
-
- »Color Drawing Operations
-
- PROCEDURE FillCRect (r: Rect; ppat: PixPatHandle);
- PROCEDURE FillCOval (r: Rect; ppat: PixPatHandle);
- PROCEDURE FillCRoundRect (r: Rect; ovWd,ovHt: INTEGER; ppat: PixPatHandle);
- PROCEDURE FillCArc (r: Rect; startAngle,arcAngle: INTEGER; ppat: PixPatHandle);
- PROCEDURE FillCRgn (rgn: RgnHandle; ppat: PixPatHandle);
- PROCEDURE FillCPoly (poly: PolyHandle; ppat: PixPatHandle);
-
- These calls are analogous to their similarly named counterparts in QuickDraw. They
- allow a multicolored pattern to be used for filling.
-
- PROCEDURE GetCPixel (h,v: INTEGER; VAR cPix: RGBColor);
-
- The GetCPixel function returns the RGB of the pixel at the specified position in the
- current port.
-
- PROCEDURE SetCPixel (h,v: INTEGER; cPix: RGBColor);
-
- The SetCPixel function sets the pixel at the specified position to the pixel value
- that most closely matches the specified RGB.
-
- _______________________________________________________________________________
-
- »Creating Pixel Maps
-
- FUNCTION NewPixMap : PixMapHandle;
-
- The NewPixMap function creates a new, initialized pixMap data structure and returns a
- handle to it. All fields of the pixMap are copied from the current device’s pixMap
- except the color table. A handle to the color table is allocated but not initialized.
-
- PROCEDURE DisposPixMap (pm: PixMapHandle);
-
- The DisposPixMap procedure releases all storage allocated by NewPixMap. It disposes
- of the pixMap’s color table, and of the pixMap itself. Be careful not to dispose of a
- pixMap whose color table is the same as the current device’s color table.
-
- PROCEDURE CopyPixMap (srcPM,dstPM: PixMapHandle);
-
- The CopyPixMap routine is used for duplicating the pixMap data structure. CopyPixMap
- copies the contents of the source pixMap data structure to the destination pixMap
- data structure. The contents of the color table are copied, so the destination pixMap
- has its own copy of the color table. Since the baseAddr field of the pixMap is a
- pointer, the pointer, but not the image itself, is copied.
-
- _______________________________________________________________________________
-
- »Operations on Pixel Maps
-
- PROCEDURE CopyBits (srcBits,dstBits: BitMap; srcRect, dstRect: Rect;
- mode: INTEGER; maskRgn: RgnHandle);
-
- CopyBits now accepts either bitMaps or pixMaps as parameters. For convenience, just
- as you could pass the current port^.portBits as a parameter to CopyBits, you can now
- pass GrafPtr(cPort)^.portBits. (Recall that in a cGrafPort the high two bits of the
- portVersion field are set. This field, in the same position in the port as portBits.rowBytes,
- indicates to QuickDraw that it has been passed a portPixMap handle.)
-
- This call transfers an image from one bitMap or pixMap to another bitMap or pixMap.
- The source and destination may be of different depths, of different sizes, and they
- may have different color tables. Note, however, that the destination pixMap is assumed
- to use the same color table as the gDevice.
- (This is because an inverse table is required for translation to the destination’s
- color table.)
-
- During a CopyBits call, the foreground and background colors are applied to the
- image. To avoid unwanted coloring of the image, set the foreground to black and the
- background to white before calling this routine.
-
- PROCEDURE CopyMask (srcBits,maskBits,dstBits: BitMap;
- srcRect,maskRect,dstRect: Rect);
-
- CopyMask is a new version of the CopyBits procedure, introduced in the Macintosh
- Plus. It transfers an image from the source to the destination only where the corresponding
- bit of the mask equals 1. The Macintosh II version will accept either a bitMap or
- pixMap as the srcBits or dstBits parameters. The maskBits parameter must be a bitMap.
-
- Like the Macintosh Plus version, CopyMask doesn’t send any of its drawing commands
- through grafProc routines; thus CopyMask calls are not recorded in pictures. Unlike
- the Macintosh Plus version, the Macintosh II version of CopyMask is able to stretch
- the source and mask to fit the dstRect. The srcRect and maskRect should be the same
- size. CopyMask uses the same low-level code as CopyBits, so all the same rules regarding
- depth translation and color table translation apply.
-
- During a CopyMask call, the foreground and background colors are applied to the
- image. To avoid unwanted coloring, set the foreground to black and the background to
- white before calling this routine.
-
- PROCEDURE SeedCFill (srcBits, dstBits: BitMap; srcRect, dstRect: Rect;
- seedH, seedV: INTEGER; matchProc: ProcPtr;
- matchData: LONGINT);
-
- The SeedCFill procedure generates a mask for use with CopyMask or CopyBits, with bits
- equal to 1 only in those positions where paint can leak from the starting seed point,
- like the MacPaint® bucket tool.
-
- Given a rectangle within a source bitMap or pixMap (srcBits), SeedCFill returns a
- mask (dstBits) that contains 1’s in place of all pixels to which paint can leak from
- the specified seed position (seedH, seedV), expressed in the local coordinate system
- of the source pixMap. By default, paint can leak to all adjacent pixels whose RGB
- value exactly match that of the seed. To use this default, set matchProc and matchData
- to zero.
-
- In generating the mask, SeedCFill performs CopyBits to convert srcBits to a
- one-bit mask. It installs a default searchProc into the gDevice that returns 0 if the
- RGB value matches that of the seed; all other RGB values return 1’s.
-
- If you want to customize SeedCFill, your application can specify a matchProc that is
- used instead of the default searchProc. It should return 0’s for RGB values that you
- want to be filled, and 1’s for values that shouldn’t be filled. When the matchProc is
- called, the GDRefCon field of the current gDevice contains a pointer to a record
- having the following structure:
-
- MatchRec = RECORD
- red: INTEGER;
- green: INTEGER;
- blue: INTEGER;
- matchData: LONGINT
- END;
-
- In this record the red, green, and blue fields are the RGB of the pixel at the specified
- seed location. MatchData is simply whatever value you passed to SeedCFill as a parameter.
- For instance, your application could pass a handle to a color table whose entries
- should all be filled, and then, in the matchProc, check to see if the specified RGB
- matches any of the colors in the table.
-
- No automatic scaling is performed: the source and destination rectangles must be the
- same size. Calls to SeedCFill are not clipped to the current port and are not stored
- into QuickDraw pictures.
-
- PROCEDURE CalcCMask (srcBits, dstBits: BitMap; srcRect, dstRect: Rect;
- seedRGB: RGBColor; matchProc: ProcPtr; matchData: LONGINT);
-
- This routine generates a mask (dstBits) corresponding to the area in a pixMap
- (srcBits) to which paint cannot leak from outside of the srcRect. The size of srcRect
- must be the same as the size of dstRect. By default, paint can leak to all adjacent
- pixels whose RGB values don’t match that of the seedRGB. To use this default, set
- matchProc and matchData to 0.
-
- For instance, if srcBits contains a blue rectangle on a red background, and your
- application calls CalcCMask with the seedRGB equal to blue, then the returned mask
- has ones in the positions corresponding to the edges and interior of the rectangle,
- and zeros outside of the rectangle.
-
- If you want to customize CalcCMask, your application can specify a matchProc that is
- used instead of the default searchProc. It should return 1’s for RGB values that
- define the edges of the mask, and 0’s for values that don’t.
-
- When the matchProc is called, the GDRefCon field of the gDevice contains a pointer to
- a MatchRec record (the structure shown in the SeedCFill description). The red, green,
- and blue fields are the RGB of the pixel at the specifed seed location. MatchData is
- simply whatever value your application passed to CalcCMask as a parameter. For instance,
- your program could pass a handle to a color table whose entries should all be within
- the mask, and then, in the matchProc, check to see if the specified RGB matches any
- of the colors in the table.
-
- No automatic scaling is performed: the source and destination rectangles must be the
- same size. Calls to CalcCMask are not clipped to the current port and are not stored
- into QuickDraw pictures.
-
- _______________________________________________________________________________
-
- »Operations on Pixel Patterns
-
- FUNCTION NewPixPat: PixPatHandle;
-
- The NewPixPat function creates a new pixPat data structure, and returns a handle to
- it. It calls NewPixMap to allocate and initialize the pattern’s pixMap to the same
- settings as theGDevice^^.GDPMap, and it sets the type of the pixPat to be a color
- pattern. The pat1Data field is initialized to a 50% gray pattern. New handles for
- data, expanded data, expanded map, and color table are allocated but not initialized.
- Including the pixPat itself, it allocates a total of six handles. You will generally
- not need to use this routine since the GetPixPat routine can be used to read in a
- pattern from a resource file.
-
- The sizes of the pixMap and pixPat handles are the size of their respective data
- structures (see the type declarations in the “Summary” section). The other three
- handles are initially small in size. Once the pattern is drawn, the size of the
- expanded data is proportional to the size of the pattern data, but adjusted to the
- depth of the screen. The color table size is the size of the record structure plus
- eight bytes times the number of colors in the table.
- _______________________________________________________________________________
-
- »Creating a PixPat
-
- To create a color pattern, use NewPixPat to allocate a new PixPatHandle. Set the
- rowBytes, bounds, and pixelSize of the pattern’s pixMap to the dimensions of the
- desired pattern. The rowBytes should be equal to (width of bounds)*pixelSize/8; it
- need not be even. The width and height of the bounds must be a power of two. Each
- scanline of the pattern must be at least one byte in length—that is, (width of bounds)*pixelSize
- must be at least eight. Set the other fields in the pattern’s pixMap as described in
- the section on the pixMap data structure.
-
- Your application can explicitly specify the color corresponding to each pixel value
- with the color table. The color table for the pattern must be placed in the pmTable
- in the pixPat’s pixMap. Patterns may also contain colors that are relative to the
- foreground and background at the time that they are drawn. Refer to the section on
- the pixPat data structure for more information on relative patterns.
-
- PROCEDURE DisposPixPat (ppat: PixPatHandle);
-
- The DisposPixPat procedure releases all storage allocated by NewPixPat. It disposes
- of the pixPat’s data handle, expanded data handle, and pixMap handle.
-
- PROCEDURE CopyPixPat (srcPP,dstPP: PixPatHandle);
-
- The CopyPixPat procedure copies the contents of the source pixPat to the destination
- pixPat. It entirely copies all fields in the source pixPat, including the contents of
- the data handle, expanded data handle, expanded map, pixMap handle, and color table.
-
- FUNCTION GetPixPat (patID: INTEGER): PixPatHandle;
-
- The GetPixPat call creates a new pixPat data structure, and then uses the information
- in the resource of type 'ppat' and the specified ID to initialize the pixPat. The
- 'ppat' resource format is described in the section “Color QuickDraw Resource Formats”.
- If the resource with the specified ID is not found, then this routine returns a NIL
- handle.
-
- PROCEDURE MakeRGBPat (ppat: PixPatHandle; myColor: RGBColor);
-
- The MakeRGBPat procedure is a new call which generates a pixPat that approximates the
- specified color when drawn. For example, if your application is drawing to a device
- that has 4 bits per pixel, you will only get 16 colors if you simply set the foreground
- color and draw. If you use MakeRGBPat to select a pattern, and then draw using that
- pattern, you will effectively get 125 different colors. More colors are theoretically
- possible; this implementation opted for a fast pattern selection rather than the best
- possible pattern selection. If the device has 8 bits per pixel, you will effectively
- get 2197 colors.
-
- Note that these patterns aren’t usually solid; they provide a wide selection of
- colors by alternating between colors with up to four colors in a pattern. For this
- reason lines that are one pixel wide may not look good using these patterns. For an
- RGB pattern, the patMap^^.bounds always contains (0, 0, 8, 8), and the patMap^^.rowbytes
- equals 2. Figure 6 shows how these colors are arranged.
-
- When MakeRGBPat creates a color table, it only fills in the last colorSpec field: the
- other colorSpec values are computed at the time the drawing actually takes place,
- using the current pixel depth for the system.
-
- Value RGB
- 0 computed RGB color
- 1 computed RGB color
- 2 computed RGB color
- 3 computed RGB color
- 4 RGBColor passed to MakeRGBPat routine
-
- •••Refer to Figure 6.•••
-
- Figure 6–RGB Pattern
-
- PROCEDURE PenPixPat (ppat: PixPatHandle);
- PROCEDURE BackPixPat (ppat: PixPatHandle);
-
- The PenPixPat and BackPixPat calls are analogous to PenPat and BackPat, but use
- multicolor pixel patterns instead of old-style patterns. If you try to use a pixel
- pattern in a grafPort, the data in the pat1Data field is placed into pnPat, bkPat, or
- fillPat.
-
- When your application sets a pixel pattern, the handle you provide is actually placed
- into the grafPort or cGrafPort. In this way, QuickDraw can expand the pattern once
- (saving it in the patXData field) when the pattern is first set, and won’t have to
- reexpand it each time you set the pattern.
-
- Since your handle is actually stored in the grafPort or cGrafPort, it’s considered
- bad form to dispose of a PixPatHandle that is currently set as the pnPixPat or bkPixPat.
- (Just in case you forget, QuickDraw will remove all references to your pattern from
- existing grafPorts or cGrafPorts when you dispose of it.)
-
- Using the old calls PenPat and BackPat, you can still set old-style patterns in a
- cGrafPort. If necessary, it creates a new pixPatHandle in which to store the pattern
- (because, as described above, pixPatHandles are owned by the application). As in old
- grafPorts, old-style patterns are drawn using the foreground and background colors at
- the time of drawing, not at the time the pattern is set.
-
- _______________________________________________________________________________
-
- »Operations on Color Cursors
-
- FUNCTION GetCCursor (crsrID: INTEGER): CCrsrHandle;
-
- The GetCCursor call creates a new CCrsr data structure, then initializes it using the
- information in the resource of type 'crsr' with the specified ID. The 'crsr' resource
- format is described in the section “Color QuickDraw Resource Formats”. If the resource
- with the specified ID isn’t found, then this routine returns a NIL handle.
-
- Since GetCCursor creates a new CCrsr data structure each time it is called, your
- application shouldn’t call GetCCursor before each call to SetCCursor
- (unlike the way GetCursor/SetCursor were normally used). GetCCursor doesn’t dispose
- or detach the resource, so resources of type 'crsr' should typically be purgeable.
-
- PROCEDURE SetCCursor (cCrsr: CCrsrHandle);
-
- The SetCCursor procedure allows your application to set a multicolor cursor. At the
- time the cursor is set, it’s expanded to the current screen depth so that it can be
- drawn rapidly.
-
- If your application has changed the cursor’s data or its color table, it must also
- invalidate the fields crsrXValid and crsrID (described in the section on the Color
- Cursor data structure), before calling SetCCursor.
-
- PROCEDURE DisposCCursor(cCrsr: CCrsrHandle);
-
- The DisposCCursor procedure disposes all structures allocated by GetCCursor.
-
- PROCEDURE AllocCursor;
-
- The AllocCursor procedure reallocates cursor memory. Under normal circumstances, you
- should never need to use this call, since reallocation of cursor memory is only
- necessary after the depth of one of the screens has been changed.
-
- _______________________________________________________________________________
-
- »Operations on Color Icons
-
- FUNCTION GetCIcon(id: INTEGER): CIconHandle;
-
- The GetCIcon function allocates a CIcon data structure and initializes it using the
- information in the resource of type 'cicn' with the specified ID. It returns the
- handle to the icon’s data structure. If the specified resource
- isn’t found, a NIL handle is returned.
-
- The format of the 'cicn' resource is described in the section “Color QuickDraw Resource
- Formats”.
-
- Since GetCIcon creates a new CIcon data structure each time it is called, your application
- shouldn’t call GetCIcon before each call to PlotCIcon. GetCIcon doesn’t dispose or
- detach the resource, so resources of type 'cicn' should typically be purgeable.
-
- PROCEDURE DisposCIcon(theIcon: CIconHandle);
-
- The DisposCIcon procedure disposes all structures allocated by GetCIcon.
-
- PROCEDURE PlotCIcon(theRect: Rect; theIcon: CIconHandle);
-
- The PlotCIcon procedure draws the specified icon in the specified rectangle. The
- iconMask field of the CIcon determines which pixels of the iconPMap are drawn and
- which are not. Only pixels with 1’s in corresponding positions in the iconMask are
- drawn; all other pixels don’t affect the destination. If the screen depth is one or
- two bits per pixel, the iconBMap is used as the source instead of the iconPMap (unless
- the rowBytes field of iconBMap is 0, indicating that there is no iconBMap.
-
- When the icon is drawn, the boundsRect of the iconPMap is used as the image’s source
- rectangle. The icon and its mask are both stretched to the destination rectangle. The
- icon’s pixels are remapped to the current depth and color table, if necessary. The
- bounds fields of the iconPMap, iconBMap, and iconMask are expected to be equal in
- size.
-
- PlotCIcon is simply a structured call to CopyMask. As such, it doesn’t send any of
- its drawing commands through grafProc routines; thus, PlotCIcon calls are not recorded
- in pictures.
-
- _______________________________________________________________________________
-
- »Operations on CGrafPort Fields
-
- PROCEDURE SetPortPix (pm: PixMapHandle);
-
- The SetPortPix call is analogous to SetPortBits, and should be used instead of SetPortBits
- for cGrafPorts. It replaces the portPixMap field of the current cGrafPort with the
- specified handle. SetPortPix has no effect when used with an old grafPort. If SetPortBits
- is called when the current port is a cGrafPort, it does nothing.
-
- PROCEDURE OpColor (color: RGBColor);
-
- If the current port is a cGrafPort, the OpColor procedure sets the red, green, and
- blue values used by the AddPin, SubPin, and Blend drawing modes. This information is
- actually stored in the grafVars handle in the cGrafPort, but you should never need to
- reference it directly. If the current port is a grafPort, OpColor has no effect.
-
- PROCEDURE HiliteColor (color:RGBColor);
-
- The highlight color is used by all drawing operations that use the highlight transfer
- mode. When a cGrafPort is created, its highlight color is initialized from the global
- variable HiliteRGB. The HiliteColor procedure allows you to change the highlighting
- color used by the current port. This information is actually stored in the grafVars
- handle in the cGrafPort, but you should never need to reference it directly. If the
- current port is a grafPort, HiliteColor has no effect.
-
- PROCEDURE CharExtra (extra:Fixed);
-
- The CharExtra procedure sets the cGrafPort’s charExtra field, which specifies the
- number of pixels by which to widen every character excluding the space character in a
- line of text. The charExtra field is stored in a compressed format based on the
- txSize field, so you must set txSize before calling CharExtra. The initial charExtra
- setting is 0. CharExtra will accept a negative number. CharExtra has no effect on
- grafPorts.
-
- PROCEDURE SetStdCProcs (VAR cProcs: CQDProcs);
-
- This procedure sets all the fields of the given CQDProcs record to point to the
- standard low-level routines. You can then change the ones you wish to point to your
- own routines. For example, if your procedure that processes picture comments is named
- MyComments, you will store @MyComments in the commentProc field of the CQD Procs
- record.
-
- When drawing in a cGrafPort, your application must always use SetStdCProcs instead of
- SetStdProcs.
-
- _______________________________________________________________________________
-
- »Operations on Color Tables
-
- FUNCTION GetCTable (ctID: INTEGER): CTabHandle;
-
- The GetCTable routine allocates a new color table data structure, and initializes it
- using the information in the resource of type 'clut' having the specified ID. If the
- specified resource is not found, a NIL handle is returned.
-
- If you place this handle into a pixMap, you should first dispose of the handle that
- was already there.
-
- The format of the 'clut' resource is given in the section “Color QuickDraw Resource
- Formats”. Resource ID values 0..127 are reserved for system use. Any
- 'clut' resources defined by your application should have IDs in the range
- 128..1023. This value must be in the ctSeed field in the resource, and will be placed
- in the ctSeed field of the color table (for color table identification). All other
- possible seed values are used to identify newly created color tables, and color
- tables that have been modified.
-
- If you modify a color table, you should invalidate it by changing its ctSeed field.
- You can get a new unique value for ctSeed using the routine GetCTSeed, described in
- the Color Manager chapter.
-
- PROCEDURE DisposCTable(cTable: CTabHandle);
-
- The DisposCTable procedure disposes the handle allocated for a color table.
-
- _______________________________________________________________________________
-
-
- æKY Color…QuickDraw…Resource…Formats
- æC »COLOR QUICKDRAW RESOURCE FORMATS ColorQuickDraw
- _______________________________________________________________________________
-
- Several new resource types have been defined for use with Color QuickDraw. They
- are
-
- 'crsr' Color cursor resource type
- 'ppat' Pixel Pattern resource type
- 'cicn' Color Icon resource type
- 'clut' Color Look-Up Table resource type
-
- The precise formats of resources of these types are given below.
-
- It is important to note that resources are used somewhat differently by Color QuickDraw.
- For instance, with old QuickDraw, you could do a GetCursor for each SetCursor, and
- the same handle would be passed back to the application each time. With Color QuickDraw,
- the color cursor, icon, and pattern are compound structures, more complex than a
- simple resource handle. Color QuickDraw reads the requested resource, copies it, and
- then alters the copy before passing it to the application. Each time you call GetCCursor,
- you get a new copy of the cursor. This means that you should do one GetCCursor call
- for a cursor, even if you do multiple SetCCursor calls. These new resource types
- should be marked as purgeable if you are concerned about memory space.
-
- Here are the resource formats of the resources used by Color QuickDraw. All offsets
- are measured from the beginning of the resource’s data.
-
- »'crsr' (Color Cursor)
-
- CCrsr {data structure describing cursor}
- crsrType: [2 bytes] = $8001
- crsrMap: [4 bytes] = offset to pixMap structure
- crsrData: [4 bytes] = offset to pixel data
- crsrXData: [4 bytes] = 0
- crsrXValid: [2 bytes] = 0
- crsrXHandle: [4 bytes] = 0
- crsr1Data: [32 bytes] = 1 bit image for cursor
- crsrMask: [32 bytes] = cursor’s mask
- crsrHotSpot: [4 bytes] = cursor’s hotSpot (v,h)
- crsrXTable: [4 bytes] = 0
- crsrID: [4 bytes] = 0
- PixMap {pixMap describing cursor’s pixel image}
- baseAddr: [4 bytes] = 0
- rowBytes: [2 bytes] = rowBytes of image
- bounds: [8 bytes] = boundary rectangle of image
- pmVersion: [2 bytes] = 0
- packType: [2 bytes] = 0
- packSize: [4 bytes] = 0
- hRes: [4 bytes] = $00480000
- vRes: [4 bytes] = $00480000
- pixelType: [2 bytes] = 0 = chunky
- pixelSize: [2 bytes] = bits per pixel in image
- cmpCount: [2 bytes] = 1
- cmpSize: [2 bytes] = pixelsize
- planeBytes: [4 bytes] = 0
- pmTable: [4 bytes] = offset to color table data
- pmReserved: [4 bytes] = 0
- pixel data [see below] data for cursor
- color table data [see below] data for color table
-
- The crsrMap field of the CCrsr record contains an offset to the pixMap record from
- the beginning of the resource data. The crsrData field of the CCrsr record contains
- an offset to the pixel data from the beginning of the resource data. The pmTable
- field of the pixMap record contains an offset to the color table data from the beginning
- of the resource data. The size of the pixelData is calculated by subtracting the
- offset to the pixel data from the offset to the color table data. The color table
- data consists of a color table record
- (ctSeed, ctFlags, ctSize) followed by ctSize+1 color table entries. Each entry in the
- color table connects a pixel value used in the pixel data to an actual RGB.
-
- »'ppat' (Pixel Pattern)
-
- PixPat record {data structure describing pattern}
- patType [2 bytes] = 1 (full color pattern)
- patMap [4 bytes] = offset to pixMap record
- patData [4 bytes] = offset to pixel data
- patXData [4 bytes] = 0
- patXValid [2 bytes] = –1
- patXMap [4 bytes] = 0
- pat1Data [8 bytes] = 1 bit pattern data
- PixMap { pixMap describing pattern’s pixel image }
- baseAddr [4 bytes] = 0
- rowBytes [2 bytes] = rowBytes of image
- bounds [8 bytes] = boundary rectangle of image
- pmVersion [2 bytes] = 0
- packType [2 bytes] = 0
- packSize [4 bytes] = 0
- hRes [4 bytes] = $00480000
- vRes [4 bytes] = $00480000
- pixelType [2 bytes] = 0 = chunky
- pixelSize [2 bytes] = bits per pixel in image
- cmpCount [2 bytes] = 1
- cmpSize [2 bytes] = pixelsize
- planeBytes [4 bytes] = 0
- pmTable [4 bytes] = offset to color table data
- pmReserved [4 bytes] = 0
- pixel data [see below] data for pattern
- color table data [see below] data for color table
-
- The patMap field of the pixPat record contains an offset to the pixMap record from
- the beginning of the resource data. The patData field of the pixPat record contains
- an offset to the pixel data from the beginning of the resource data. The pmTable
- field of the pixMap record contains an offset to the color table data from the beginning
- of the resource data. The size of the pixelData is calculated by subtracting the
- offset to the pixel data from the offset to the color table data. The color table
- data consists of a color table record
- (ctSeed, ctFlags, ctSize) followed by ctSize+1 color table entries. Each entry in the
- color table connects a pixel value used in the pixel data to an actual RGB.
-
- »'cicn' (Color Icon)
-
- IconPMap {pixMap describing icon’s pixel image}
- baseAddr [4 bytes] = 0
- rowBytes [2 bytes] = rowBytes of image
- bounds [8 bytes] = boundary rectangle of image
- pmVersion [2 bytes] = 0
- packType [2 bytes] = 0
- packSize [4 bytes] = 0
- hRes [4 bytes] = $00480000
- vRes [4 bytes] = $00480000
- pixelType [2 bytes] = 0 = chunky
- pixelSize [2 bytes] = bits per pixel in image
- cmpCount [2 bytes] = 1
- cmpSize [2 bytes] = pixelsize
- planeBytes [4 bytes] = 0
- pmTable [4 bytes] = 0
- pmReserved [4 bytes] = 0
- IconMask {Mask used when drawing icon}
- baseAddr [4 bytes] = 0
- rowBytes [2 bytes] = rowBytes of image
- bounds [8 bytes] = boundary rectangle of image
- IconBMap {Image used when drawing to 1 bit screen}
- baseAddr [4 bytes] = 0
- rowBytes [2 bytes] = rowBytes of image
- bounds [8 bytes] = boundary rectangle of image
- IconData {placeholder for image’s handle}
- [4 bytes] = 0
- MaskData {the icon’s mask data }
- [n bytes] n = IconMask.rowBytes*height
- BMapData {the icon’s bitMap data }
- [n bytes] n = IconBMap.rowBytes*height
- PMapCTab {the icon’s color table }
- [n bytes] n = 8+(ColorTable.ctSize+1)*CTEntrySize
- PMapData {the icon’s image data }
- [n bytes] n = IconPMap.rowBytes*height
-
- In the calculations above:
-
- height = IconPMap^^.bounds.bottom–IconPMap^^.bounds.top.
-
- IconPMap is the pixMap describing the data in the IconData field. IconMask is the
- mask that is to be applied to the data when it is drawn. IconBMap is a bitMap to be
- drawn when the destination is only one or two pixels deep. If the rowbytes field of
- IconBMap is 0, then no data is loaded in for the IconBMap, and IconPMap is always
- used when drawing the icon. MaskData is the mask’s data. It is immediately followed
- by the bitMap’s data (which may be NIL). Next is the color table describing the
- IconPMap, as shown below. The final entry in the resource is the pixMap’s data.
-
- »'clut' (Color Table)
-
- ctSeed [4 bytes] = 0
- ctFlags [2 bytes] = $0000 if pixMap color table
- = $8000 if device color table
- ctSize [2 bytes] = #entries – 1
- table data [n bytes] n = 8*(ctSize+1)
-
- The 'clut' resource format is an exact duplicate of a color table in memory. Each
- element in the table data is four integers (eight bytes): a value field followed by
- red, green, and blue values. If the color table is used to describe a pixMap, then
- ctFlags should be set to 0, and the value field of each entry contains the pixel
- value to be associated with the following RGB. If the color table is used to describe
- a device, then ctFlags should be set to $8000, and the value fields should be set to
- 0. In this case, the implicit values are based on each entry’s position in the
- table.
-
- There are several default color tables that are in the Macintosh II ROMs. There is
- one for each of the standard pixel depths. The resource ID for each table is the
- same as the depth. For example, the default color table used when you switch your
- system to 8 bits per pixel mode is stored with resource ID = 8.
-
- There is one other default color table. This color table defines the eight QuickDraw
- colors, the colors displayed by programs using the old QuickDraw model. This color
- table has ID = 127. Its values are given in the section
- “Setting the Foreground and Background Colors”.
-
- _______________________________________________________________________________
-
-
- æKY Using…Text…with…QuickDraw
- æC »USING TEXT WITH QUICKDRAW ColorQuickDraw
- _______________________________________________________________________________
-
- This section explains those QuickDraw features which provide enhanced text handling
- for the Macintosh Plus, Macintosh SE, and Macintosh II. The drawing mode recommended
- for all applications is SrcOr, because it uses the least memory and will draw the
- entire character in all cases. The SrcOr mode will only affect other parts of existing
- characters if the characters overlap. In srcOr mode the color of the character is
- determined by the foreground color, although text drawing is fastest when the foreground
- color is black.
-
- With QuickDraw, characters can kern to the left and to the right. QuickDraw begins
- drawing a series of characters at the specified pen position plus the kernMax field
- (part of the Font record), plus any kerning below the baseline caused by italicizing
- the font. (The kernMax field denotes the kerning allowed by a given font; since its
- value is normally negative, most fonts kern to the left. Italicizing also normally
- moves the pen to the left.) QuickDraw then draws through the ending pen position,
- plus any kerning above the baseline caused by italicizing the font (normally to the
- right), plus any space required to handle the outlined or shadowed part of the character.
-
- To draw text in any mode, including the kerned part of the leading and trailing
- characters, it is best to draw the entire line of text at once. If the line must be
- drawn in pieces, it is best to end each piece with a space character, so that the
- succeeding piece can harmlessly kern left, and the last character drawn (a space)
- will not have any right kerning clipped.
-
- Macintosh Plus and Macintosh SE Note: The Macintosh Plus and Macintosh SE
- versions of QuickDraw clip a leading
- left-kerning character, and do not take
- italicizing into account when
- positioning the pen. Also, it adds a
- constant of 32 to the width of the
- character imaging rectangle, causing
- large italicized fonts to have the
- rightmost character clipped in drawing
- modes other than srcOr.
-
- The outline and shadow styles cause the outline and shadow of the character to be
- drawn in the foreground color. The inside of the character, if drawn at all, is drawn
- in the background color. The center of shadowed or outlined text is drawn in a grafPort
- in scrBic mode if the text mode is srcOr, for compatibility with old applications.
- This allows black text with a white outline on an arbitrary background. If the text
- mode is srcBic, the center of shadowed or outlined text is drawn in srcOr.
-
- The style underline draws the underline through the entire text line, from the pen
- starting position through the ending position, plus any offsets from font or italic
- kerning, as described above. If the underline is outlined or shadowed, the ends
- aren’t capped, that is, consecutively drawn pieces of text should maintain a continuous
- underline.
-
- Macintosh Plus and Macintosh SE Note: QuickDraw clips the right edge of the
- underline to the ending pen position,
- causing outlined or shadowed underlines
- to match imperfectly when text is drawn
- in sections.
-
- One of the reasons that SrcOr is recommended is that the maximum stack space required
- for a text font drawing operation can be considerable. Text drawing uses a minimum
- amount of stack if the mode is srcOr, the forecolor is black, the visRgn and clipRgn
- are rectangular (or at least the destination of the text is contained within a rectangular
- portion of the visRgn), the text is not scaled, and the text does not have to be
- italicized, boldfaced, outlined, or shadowed by QuickDraw. Otherwise, the amount of
- stack required to draw all of the text at once depends most on the size and width of
- the the text and the depth of the destination.
-
- If QuickDraw can’t get enough stack space to draw an entire string at once, it will
- draw the string in pieces. This can produce disconcerting results in modes other than
- srcOr or srcBic if some of the characters overlap because of kerning or italicizing.
- If the mode is srcCopy, overlapping characters will be clipped by the last drawn
- character. If the mode is srcXor, pixels where the characters overlap are not drawn
- at all. If the mode is one of the arithmetic modes, the arithmetic rules are followed,
- ignoring that the destination may include part of the string being drawn.
-
- The stack space required for a drawing operation on the Macintosh II is roughly given
- by this calculation:
-
- (text width) * (text height) * (font depth) / (8 bits per byte ) + 3K
-
- Font depth normally equals the screen depth. If the amount of stack space available
- is small (less than 3.5K), QuickDraw instead uses a font depth of 1, which is slow,
- but uses less stack space.
-
- On the Macintosh Plus, the required stack space is roughly equal to
-
- (text width) * (text height) / (8 bits per byte ) + 2K
-
- _______________________________________________________________________________
-
- »Text Mask Mode
-
- For the Macintosh II, the maskConstant may be added to another drawing mode to cause
- just the character portion of the text to be applied in the current transfer mode to
- the destination. If the text font contains more than one color, or if the drawing
- mode is an arithmetic mode or hilite mode, the mask mode causes only the portion of
- the characters not equal to the background to be drawn.
-
- The arithmetic drawing modes and hilite mode apply the character’s background to the
- destination; this can lead to undesirable results if the text is drawn in pieces. The
- leftmost part of a text piece is drawn on top of a previous text piece if the font
- kerns to the left. The maskMode supplied in addition to these modes causes only the
- foreground part of the character to be drawn. The only reasonable way to kern to the
- right in text mask mode is to use srcOr, or to add trailing characters. This is
- because the rightmost kern is clipped.
-
- The constant used with maskMode is
-
- CONST
- mask = 64;
-
- _______________________________________________________________________________
-
- »Drawing with Multibit Fonts
-
- Multibit fonts may have a specific color. The transfer modes may not produce the
- desired results with a multibit font. The arithmetic modes, transparent mode, and
- hilite mode work equally well with single bit and multibit fonts.
-
- Unlike single bit fonts, multibit fonts draw quickly in srcOr only if the foreground
- is white. Single bit fonts draw quickly in srcOr only if the foreground is black.
- Grayscale fonts produce a spectrum of colors, rather than just the foreground and
- background colors.
-
- _______________________________________________________________________________
-
- »Fractional Character Positioning
-
- CGrafPorts maintain the fractional horizontal pen position, so that a series of text
- drawing calls will accumulate the fractional position. The horizontal pen fraction is
- initially set to 1/2. InitPort, Move, MoveTo, Line and LineTo reset the pen position
- to 1/2. For an old grafPort, the pen fraction is hard-coded to 1/2.
-
- _______________________________________________________________________________
-
-
- æKY Color…Picture…Format
- æC »COLOR PICTURE FORMAT ColorQuickDraw
- _______________________________________________________________________________
-
- With the introduction of the Macintosh II, the QuickDraw picture structure has been
- extended to include new color graphics opcodes. The new version 2 pictures and opcodes
- solve many of the major problems encountered by developers in using PICT files, and
- enable future expandibility. For example, it is now possible to specify the resolution
- of bitMap data. Color can also be specified, but only chunky pixels (contiguously
- stored pixel components) are currently recognized by Color QuickDraw. Your application
- only needs to generate or recognize the chunky pixel format. This format is indicated
- by an image or pixMap with a cmpCount = 1.
-
- Most existing applications can use version 2 pictures without modification. On a
- Macintosh II, version 2 pictures will draw in color (if drawn directly to the screen).
- Currently, they will print using the old QuickDraw colors. Eventually, new print
- drivers will be able to take advantage of the new color information.
-
- On a Macintosh 512K enhanced, Macintosh Plus, and Macintosh SE, a patch in the System
- file beginning with version 4.1 provides QuickDraw with the capability to convert and
- display version 2 pictures. The original Macintosh and Macintosh 512 can’t display
- version 2 pictures.
-
- Applications that generate pictures in the QuickDraw picture format are free to use
- any or all available features to support their particular needs. Some will use only
- the imaging features. You may wish to include comments in the picture that are pertinent
- to the needs of your application. In general, put a minimal amount of information
- in your PICT files and avoid redundancy. It’s reasonable for receiving applications
- to ignore picture opcodes that aren’t needed.
-
- _______________________________________________________________________________
-
- »Differences Between Version 1 and Version 2 Pictures
-
- The major differences between version 1 and version 2 pictures are listed below.
-
- • Version 1 opcodes are a single byte; version 2 opcodes are 2 bytes in
- length. This means that old opcodes in a version 2 picture take up two
- bytes, not one.
- • Version 1 data may start on byte boundaries; version 2 opcodes and data
- are always word-aligned.
- • In version 2, the high bit of the rowBytes field is used to indicate a
- pixMap instead of a bitMap; pixData then replaces bitData.
- • All unused version 2 opcodes, as well as the number of data bytes
- associated with each, have been defined. This was done so that picture
- parsing code can safely ignore unknown opcodes, enabling future use
- of these opcodes in a backward-compatible manner.
-
- _______________________________________________________________________________
-
- »Drawing With Version 2 Pictures in Old GrafPorts
-
- Enhancements to the DrawPicture routine allow pictures created with Color QuickDraw
- to be used in either a cGrafPort or an old-style grafPort. You can create a picture
- using the new drawing commands in a cGrafPort, cut it, and then paste it into an
- application that draws into an old grafPort. The picture will lose some of its detail
- when transferred in this way, but should be sufficient for most purposes. The following
- considerations apply to the use of this technique:
-
- • The rgbFgColor and rbgBkColor fields are mapped to the old-style
- Quickdraw constant (one of eight) that most closely approximates that
- color. For a grafPort with depth greater than one, even old applications
- will be able to draw color pictures.
- • Patterns created using MakeRGBPat are drawn as old-style patterns having
- approximately the same luminance as the original pattern.
- • Other new patterns are replaced by the old-style pattern contained
- in the pat1Data field of the PixPat data structure. This field is
- initialized to 50% gray by the NewPixPat routine, and is initialized
- from the resource in a GetPixPat call.
- • PixMaps in the picture are drawn without interpretation. The CopyBits
- call performs all necessary mapping to the destination screen. If
- the picture is drawn on a Macintosh Plus or a Macintosh SE, or if the
- BitsProc routine has been replaced by the application, the pixMap is
- converted to a bitMap before it’s drawn.
- • Changes to the ChExtra and pnLocHFrac fields, and the Hilite color
- and OpColor, are ignored.
-
- A new standard opcodeProc, SetStdCProc, is called by QuickDraw when it is playing
- back a color picture and it sees a new opcode that it doesn’t recognize. The default
- routine simply reads and ignores all undefined opcodes.
-
- _______________________________________________________________________________
-
- »Picture Representation
-
- The PICT file is a data fork file with a 512-byte header, followed by a picture (see
- Figure 7). This data fork file contains a QuickDraw (and now, Color QuickDraw) data
- structure within which a graphic application, using standard QuickDraw calls, places
- drawing opcodes to represent an object or image graphic data. In the QuickDraw
- picture format, pictures consist of opcodes followed by picture data.
-
- •••Refer to Figure 7.•••
-
- Figure 7–PICT file format.
-
- _______________________________________________________________________________
-
- »Picture Parsing
-
- The first 512 bytes of a PICT data file contain application-specific header information.
- Each QuickDraw (and Color QuickDraw) picture definition consists of a fixed-size
- header containing information about the size, scaling, and version of the picture,
- followed by the opcodes and picture data defining the objects drawn between the
- OpenPicture and ClosePicture calls.
-
- When the OpenPicture routine is called and the port is an old grafPort, a version 1
- picture is opened. When the OpenPicture routine is called and the port is a cGrafPort,
- then a version 2 picture is opened. If any fields in the grafPort are different than
- the default entries, those fields that are different get recorded in the picture.
-
- Version 4.1 of the Macintosh System file incorporates a patch to QuickDraw that will
- enable QuickDraw (on machines with 128K or larger ROMs) to parse a version 2 PICT
- file, read it completely, attempt to convert all Color QuickDraw color opcodes to a
- suitable black-and-white representation, and draw the picture in an old grafPort. If
- you are trying to display a version 2 picture on a Macintosh without the system
- patch, QuickDraw won’t be able to draw the picture.
-
- _______________________________________________________________________________
-
- »Picture Record Structure
-
- The Pascal record structure of version 1 and version 2 pictures is exactly the same.
- In both, the picture begins with a picSize, then a picFrame (rect), followed by the
- picture definition data. Since a picture may include any sequence of drawing commands,
- its data structure is a variable-length entity. It consists of two fixed-length
- fields followed by a variable-length field:
-
- TYPE Picture = RECORD
- picSize: INTEGER; {low order 16 bits of picture }
- { size}
- picFrame: Rect; {picture frame, used as }
- { reference for scaling when }
- { the picture is drawn }
- {picture definition data}
- END;
-
- To maintain compatibility with the original picture format, the picSize field has not
- been changed in version 2 pictures. However, the information in this field is only
- useful if your application supports version 1 pictures not exceeding 32K bytes in
- size. Because pictures can be much larger than the 32K limit imposed by the 2-byte
- picSize field, use the GetHandleSize call to determine picture size if the picture is
- in memory or the file size returned in pBFGetInfo if the picture resides in a file.
-
- The picFrame field is the picture frame that surrounds the picture and gives a frame
- of reference for scaling when the picture is played back. The rest of the structure
- contains a compact representation of the image defined by the opcodes. The picture
- definition data consists of a sequence of the opcodes listed in Table 3 in the Pict
- Opcodes section, each followed by zero or more bytes of data. Every opcode has an
- implicit or explicit size associated with it that indicates the number of data bytes
- following that opcode, ranging from 2 to
- 2^32 bytes (this maximum number of bytes applies to version 2 pictures only).
-
- _______________________________________________________________________________
-
- »Picture Spooling
-
- In the past, images rarely exceeded the 32K practical limit placed on resources.
- Today, with the advent of scanners and other image input products, images may easily
- exceed this size. This increase in image size necessitates a means for handling
- pictures that are too large to reside entirely in memory. One solution is to place
- the picture in the data fork of a PICT file, and spool it in as needed. To read the
- file, an application can simply replace the QuickDraw default getPicProc routine with
- a procedure (getPICTData) that reads the picture data from a disk file; the disk
- access would be transparent. Note that this technique applies equally to version 1
- (byte-opcode) and version 2
- (word-opcode) pictures.
-
- »Spooling a Picture From Disk
-
- In order to display pictures of arbitrary size, an application must be able to import
- a QuickDraw picture from a file of type PICT. (This is the file type produced by a
- Save As command from MacDraw® with the PICT option selected.) What follows is a
- small program fragment that demonstrates how to spool in a picture from the data fork
- of a PICT file. The picture can be larger than the historical 32K resource size
- limitation.
-
- { The following variable and procedure must be at the }
- { main level of the program }
- VAR
- globalRef: INTEGER;
-
- PROCEDURE GetPICTData(dataPtr: Ptr; byteCount: INTEGER);
- {replacement for getPicProc routine}
-
- VAR
- err : INTEGER;
- longCount: LONGINT;
-
- BEGIN
- longCount := byteCount;
- {longCount is a Pascal VAR parameter and must be a LONGINT}
- err := FSRead(globalRef,longCount,dataPtr);
- {ignore errors here since it is unclear how to handle them}
- END;
-
- PROCEDURE GetandDrawPICTFile;
- {procedure to draw in a picture from a PICT file selected by the user}
-
- VAR
- wher: Point; {where to display dialog}
- reply: SFReply; {reply record}
- myFileTypes: SFTypeList; {more of the Standard File goodies}
- NumFileTypes: INTEGER;
- err: OSErr;
- myProcs: QDProcs; {use CQDProcs for a CGrafPort (a color }
- { window)}
- PICTHand: PicHandle; {we need a picture handle for DrawPicture}
- longCount: LONGINT;
- myPB: ParamBlockRec;
-
- BEGIN
- wher.h := 20;
- wher.v := 20;
- NumFileTypes := 1; {Display PICT files}
- myFileTypes[0] := 'PICT';
- SFGetFile(wher,'',NIL,NumFileTypes,myFileTypes,NIL,reply);
- IF reply.good THEN BEGIN
- err := FSOpen(reply.fname,reply.vrefnum,globalRef);
-
- SetStdProcs(myProcs); {use SetStdCProcs for a CGrafPort}
- myWindow^.grafProcs := @myProcs;
- myProcs.getPicProc := @GetPICTData;
-
- PICTHand := PicHandle(NewHandle(SizeOf(Picture)));
- {get one the size of (size word + frame rectangle)}
-
- {skip (so to speak) the MacDraw header block}
- err := SetFPos(globalRef,fsFromStart,512);
- longCount := SizeOf(Picture);
- {read in the (obsolete) size word and the picture frame}
- err := FSRead(globalRef,longCount,Ptr(PICTHand^));
-
- DrawPicture(PICTHand,PICTHand^^.picFrame);
- {inside of DrawPicture, QD makes repeated calls to }
- { getPicProc to get actual picture opcodes and data. Since }
- { we have intercepted GetPicProc, QD will call myProcs to }
- { get getPicProc, instead of calling the default procedure}
-
- err := FSClose(globalRef);
-
- myWindow^.grafProcs := NIL;
- DisposHandle(Handle(PICTHand));
-
- END; {IF reply.good}
- END;
-
- »Spooling a Picture to a File
-
- Spooling a picture out to a file is equally straightforward. By replacing the standard
- putPicProc with your own procedure, you can create a PICT file and spool the picture
- data out to the file.
-
- Here is a sample of code to use as a guide:
-
- {these variables and PutPICTData must be at the main program level}
- VAR PICTcount: LONGINT; {the current size of the picture}
- globalRef: INTEGER; {the file system reference number}
- newPICThand: PicHandle;
- {this is the replacement for the StdPutPic routine}
- PROCEDURE PutPICTData(dataPtr: Ptr; byteCount: INTEGER);
- VAR longCount: LONGINT;
- err: INTEGER;
- BEGIN {unfortunately, we don't know what to do with errors}
- longCount := byteCount;
- PICTCount := PICTCount + byteCount;
- err := FSWrite(globalRef, longCount, dataPtr); {ignore error…}
- IF newPICTHand <> NIL THEN newPICTHand^^.picSize := PICTCount;
- {update so QD can track the size for oddness and pad out to full words}
- END;
- {Note that this assumes the picture is entirely in memory which wouldn't }
- { always be the case. You could (in effect) be feeding the StdGetPic }
- { procedure at the same time, or simply spooling while drawing.}
- PROCEDURE SpoolOutPICTFile(PICTHand: PicHandle {the picture to spool});
- VAR err: OSErr;
- i: INTEGER;
- wher: Point; { where to display dialog }
- longCount, Zero: LONGINT;
- pframe: Rect;
- reply: SFReply; { reply record }
- myProcs: QDProcs; {use CQDProcs for a CGrafPort (a color window)}
- BEGIN
- wher.h := 20;
- wher.v := 20;
- {get a file to output to}
- SFPutFile(wher, 'Save the PICT as:', 'untitled', NIL, reply);
- IF reply.good THEN
- BEGIN
- err := Create(reply.fname, reply.vrefnum, '????', 'PICT');
- IF (err = noerr) | (err = dupfnerr) THEN
- BEGIN
- {now open the target file and prepare to spool to it}
- signal(FSOpen(reply.fname, reply.vrefnum, globalRef));
- SetStdProcs(myProcs); {use SetStdCProcs for a CGrafPort}
- myWindow^.grafProcs := @myProcs;
- myProcs.putPicProc := @putPICTdata;
- Zero := 0;
- longCount := 2;
- PICTCount := SizeOf(Picture);
- {now write out the 512 byte header and zero (initially) the}
- { Picture structure}
- FOR i := 1 TO (512 + SizeOf(Picture)) DIV longCount DO
- Signal(FSWrite(globalRef, longCount, @Zero));
- {open a new picture and draw the old one to it; this will convert}
- { the old picture to fit the type of GrafPort to which we are}
- { currently set}
- pFrame := PICThand^^.picFrame;
- newPICTHand := NIL;
- newPICTHand := OpenPicture(pFrame);
- DrawPicture(PICTHand, pFrame); {draw the picture so the
- bottleneck will be used. In real life you could be spooling while
- doing drawing commands (you might not use DrawPicture)}
- ClosePicture;
- Signal(SetFPos(globalRef, fsFromStart, 512));
- {skip the MacDraw header}
- longCount := SizeOf(Picture);
- {write out the correct (low word of the) size and the frame at}
- { the beginning}
- Signal(FSWrite(globalRef, longCount, Ptr(newPICTHand^)));
- Signal(FSClose(globalRef));
- myWindow^.grafProcs := NIL;
- KillPicture(newPICTHand);
- END
- ELSE
- Signal(err);
- END; {IF reply.good}
- END; {OutPICT}
-
- »Drawing to an Offscreen Pixel Map
-
- With the advent of high resolution output devices such as laser printers, it has
- become necessary to support bitmap images at resolutions higher than those supported
- by the screen. To speed up the interactive manipulation of high-resolution pixel map
- images, developers may want to first draw them into an off screen pixel map at screen
- resolution and retain this screen version as long as the document is open.
-
- Note: You can use the formula shown in the section “Sample PICT file” to
- calculate the resolution of the source data. How to draw into an
- offscreen pixmap is described in Macintosh Technical Note #120,
- “Drawing Into an Off-Screen Pixel Map”; the Graphics Devices chapter
- also contains a section describing how to draw to an offscreen device.
-
- _______________________________________________________________________________
-
- »New GrafProcs Record
-
- The entire opcode space has been defined or reserved, as shown in the PICT Opcodes
- section in Table 3, and a new set of routines has been added to the grafProcs record.
- These changes provide support for anticipated future enhancements in a way that won’t
- cause old applications to crash. It works like this: when Color QuickDraw encounters
- an unused opcode, it calls the new opcodeProc routine to parse the opcode data. By
- default, this routine simply ignores the data, since no new opcodes are defined
- (other than HeaderOp, which is also ignored).
-
- Color QuickDraw has replaced the QDProcs record with a CQDProcs record. In a new
- grafPort, you should never use the SetStdProcs routine. If you do, it will return
- the old QDProcs record, which won’t contain an entry for the stdOpcodeProc. If you
- don’t use the new SetStdCProcs routine, the first color picture that you try to
- display may crash your system.
- The CQDProcs record structure is shown below. Only the last seven fields are new; the
- rest of the fields are the same as those in the QDProcs record.
-
- CQDProcsPtr = ^CQDProcs
- CQDProcs = RECORD
- textProc: Ptr;
- lineProc: Ptr;
- rectProc: Ptr;
- rRectProc: Ptr;
- ovalProc: Ptr;
- arcProc: Ptr;
- polyProc: Ptr;
- rgnProc: Ptr;
- bitsProc: Ptr;
- commentProc: Ptr;
- txMeasProc: Ptr;
- getPicProc: Ptr;
- putPicProc: Ptr;
- opcodeProc: Ptr; {fields added to QDProcs}
- newProc1: Ptr; {reserved for future use}
- newProc2: Ptr; {reserved for future use}
- newProc3: Ptr; {reserved for future use}
- newProc4: Ptr; {reserved for future use}
- newProc5: Ptr; {reserved for future use}
- newProc6: Ptr; {reserved for future use}
- END;
-
- _______________________________________________________________________________
-
- »Picture Compatibility
-
- Many applications already support PICT resources larger than 32K. The 128K ROMs (and
- later) allow pictures as large as memory (or spooling) will accommodate. This was
- made possible by having QuickDraw ignore the size word and simply read the picture
- until the end-of-picture opcode is reached.
-
- Note: For maximum safety and convenience, let QuickDraw generate and
- interpret your pictures.
-
- While the PICT data formats described in this section allow you to read or write
- picture data directly, it’s best to let DrawPicture or OpenPicture and ClosePicture
- process the opcodes.
-
- One reason to read a picture directly by scanning the opcodes is to disassemble it;
- for example, extracting a Color QuickDraw pixel map to store in a private data structure.
- This shouldn’t normally be necessary, unless your application is running on a CPU
- other than the Macintosh. You wouldn’t need to do it, of course, if you were using
- Color QuickDraw.
-
- If your application does use the picture data, be sure it checks the version information.
- You may want to include an alert box in your application, indicating to users whether
- a picture was created using a later version of the picture format than is currently
- recognized by your application, and letting them know that some elements of the
- picture can’t be displayed. If the version information indicates a QuickDraw picture
- version later than the one recognized by your application, your program should skip
- over the new opcodes and only attempt to parse the opcodes it knows.
-
- As with reading picture data directly, it’s best to use QuickDraw to create data in
- the PICT format. If you need to create PICT format data directly, it’s essential that
- you understand and follow the format presented in Table 3 and thoroughly test the
- data produced on both color and black and white Macintosh machines.
-
- _______________________________________________________________________________
-
- »Picture Format
-
- This section describes the internal structure of the QuickDraw picture, consisting of
- a fixed-length header (which is different for version 1 and version 2 pictures),
- followed by variable-sized picture data. Your picture structure must follow the order
- shown in the examples below.
-
- The two fixed-length fields, picSize and picFrame, are the same for version 1 and
- version 2 pictures.
-
- picSize: INTEGER; {low-order 16 bits of picture size}
- picFrame: RECT; {picture frame, used as scaling reference}
-
- Following these fields is a variable amount of opcode-driven data. Opcodes represent
- drawing commands and parameters that affect those drawing commands in the picture.
- The first opcode in any picture must be the version opcode, followed by the version
- number of the picture.
-
- »Picture Definition: Version 1
-
- In a version 1 picture, the version opcode is $11, which is followed by version
- number $01. When parsing a version 1 picture, Color QuickDraw (or a patched QuickDraw)
- assumes it’s reading an old picture, fetching a byte at a time as opcodes. An end-of-picture
- byte ($FF) after the last opcode or data byte in the file signals the end of the data
- stream.
-
- Picture Header (fixed size of 2 bytes):
-
- $11 BYTE {version opcode}
- $01 BYTE {version number of picture}
-
- Picture Definition Data (variable sized):
-
- opcode BYTE {one drawing command}
- data . . .
- opcode BYTE {one drawing command}
- data . . .
-
- $FF {end-of-picture opcode}
-
- »Picture Definition: Version 2
-
- In a version 2 picture, the first opcode is a two-byte version opcode ($0011). This
- is followed by a two-byte version number ($02FF). On machines without the 4.1 System
- file, the first $00 byte is skipped, then the $11 is interpreted as a version opcode.
- On a Macintosh II (or a Macintosh with System file 4.1 or later), this field identifies
- the picture as a version 2 picture, and all subsequent opcodes are read as words
- (which are word-aligned within the
- picture). On a Macintosh without the 4.1 System patch, the $02 is read as the version
- number, then the $FF is read and interpreted as the end-of-picture opcode. For this
- reason, DrawPicture terminates without drawing anything.
-
- Picture Header (fixed size of 30 bytes):
-
- $0011 WORD {version opcode}
- $02FF WORD {version number of new picture}
-
- $0C00 WORD {reserved header opcode}
- 24 bytes of data {reserved for future Apple use}
-
- Picture Definition Data (variable sized):
-
- opcode WORD {one drawing command}
- data . . .
- opcode WORD {one drawing command}
- data . . .
-
- $00FF WORD {end-of-picture opcode}
-
- For future expandibility, the second opcode in every version 2 picture must be a
- reserved header opcode, followed by 24 bytes of data that aren’t used by your application.
-
- »PicComments
-
- If your application requires capability beyond that provided by the picture opcodes,
- the picComment opcode allows data or commands to be passed directly to the output
- device. PicComments enable MacDraw, for example, to reconstruct graphics primitives
- not found in QuickDraw (such as rotated text) that are received either from the
- Clipboard or from another application. PicComments are also used as a means of communicating
- more effectively with the LaserWriter and with other applications via the scrap or
- the PICT data file.
-
- Because some operations (like splines and rotated text) can be implemented more
- efficiently by the LaserWriter, some of the picture comments are designed to be
- issued along with QuickDraw commands that simulate the commented commands on the
- Macintosh screen. If the printer you are using has not implemented the comment commands,
- it ignores them and simulates the operations using the accompanying QuickDraw commands.
- Otherwise, it uses the comments to implement the desired effect and ignores the
- appropriate QuickDraw-simulated commands.
-
- If you are going to produce or modify your own picture, the structure and use of
- these comments must be precise. The comments and the embedded QuickDraw commands must
- come in the correct sequence in order to work properly.
-
- Note: Apple is currently investigating a method to register picComments.
- If you intend to use new picComments in your application, you must
- contact Apple’s Developer Technical Support to avoid conflict with
- picComment numbers used by other developers.
-
- »Sample PICT File
-
- An example of a version 2 picture data file that can display a single image is shown
- in Table 1. Applications that generate picture data should set the resolution of the
- image source data in the hRes and vRes fields of the PICT file. It’s recommended,
- however, that you calculate the image resolution anyway, using the values for srcRect
- and dstRect according to the following formulas:
-
- horizontal resolution (hRes) = width of srcRect x 72
- ________________
- width of dstRect
-
- vertical resolution (vRes) = height of srcRect x 72
- _________________
- height of dstRect
-
- Table 1–PICT file example
- _______________________________________________________________________________
- Size Name Description
- (in bytes)
- 2 picSize low word of picture size
- 8 picFrame rectangular bounding box of picture,
- at 72 dpi
- Picture Definition Data:
-
- 2 version op version opcode = $0011
- 2 version version number = $02FF
- 2 Header op header opcode = $0C00
- 4 size total size of picture in bytes
- (–1 for version 2 pictures)
- 16 fBBox fixed-point bounding box
- (–1 for version 2 pictures)
- 4 reserved reserved for future Apple use
- (–1 for version 2 pictures)
- 2 opbitsRect bitMap opcode = $0090
- 2 rowBytes integer, must have high bit set to
- signal pixMap
- 8 bounds rectangle, bounding rectangle at
- source resolution
- 2 pmVersion integer, pixMap version number
- 2 packType integer, defines packing format
- 4 packSize LongInt, length of pixel data
- 4 hRes fixed, horizontal resolution (dpi) of
- source data
- 4 vRes fixed, vertical resolution (dpi) of
- source data
- 2 pixelType integer, defines pixel type
- 2 pixelSize integer, number of bits in pixel
- 2 cmpCount integer, number of components in pixel
- 2 cmpSize integer, number of bits per component
- 4 planeBytes LongInt, offset to next plane
- pmTable color table = 0
- pmReserved reserved = 0
- 4 ctSeed LongInt, color table seed
- 2 ctFlags integer, flags for color table
- 2 ctSize integer, number of entries in ctTable –1
- (ctSize+1) * 8 ctTable color lookup table data
- 8 srcRect rectangle, source rectangle at source
- resolution
- 8 dstRect rectangle, destination rectangle at 72 dpi
- resolution
- 2 mode integer, transfer mode
- see Table 5 pixData pixel data
- 2 endPICT op end-of-picture opcode = $00FF
- _______________________________________________________________________________
-
- »Color Picture Routines
-
- FUNCTION OpenPicture (picFrame: Rect) : PicHandle;
-
- The OpenPicture routine has been modified to take advantage of QuickDraw’s new color
- capabilities. If the current port is a cGrafPort, then OpenPicture automatically
- opens a version 2 picture, as described in the previous section. As before, you close
- the picture using ClosePicture and draw the picture using DrawPicture.
-
- _______________________________________________________________________________
-
-
- æKY PICT…Opcodes
- æC »PICT OPCODES ColorQuickDraw
- _______________________________________________________________________________
-
- The opcode information in Table 3 is provided for the purpose of debugging application-generated
- PICT files. Your application should generate and read PICT files only by using standard
- QuickDraw or Color QuickDraw routines
- (OpenPicture, ClosePicture).
-
- The data types listed in Table 2 are used in the Table 3 opcode definitions. Data
- formats are described in Volume I.
-
- Table 2–Data types
- _______________________________________________________________________________
- Type Size
-
- v1 opcode 1 byte
- v2 opcode 2 bytes
- integer 2 bytes
- long integer 4 bytes
- mode 2 bytes
- point 4 bytes
- 0..255 1 byte
- –128..127 1 byte (signed)
- rect 8 bytes (top, left, bottom, right: integer)
- poly 10+ bytes
- region 10+ bytes
- fixed-point number 4 bytes
- pattern 8 bytes
- rowbytes 2 bytes (always an even quantity)
- _______________________________________________________________________________
-
- Valid picture opcodes are listed in Table 3. New opcodes or those altered for version
- 2 picture files are indicated by a leading asterisk (*). The unused opcodes found
- throughout the table are reserved for Apple use. The length of the data that follows
- these opcodes is pre-defined, so if they are encountered in pictures, they can simply
- be skipped. By default, Color QuickDraw reads and then ignores these opcodes.
-
- Table 3–PICT opcodes
- _______________________________________________________________________________
- Opcode Name Description Data Size
- (in bytes)
- $0000 NOP nop 0
- $0001 Clip clip region size
- $0002 BkPat background pattern 8
- $0003 TxFont text font (word) 2
- $0004 TxFace text face (byte) 1
- $0005 TxMode text mode (word) 2
- $0006 SpExtra space extra (fixed point) 4
- $0007 PnSize pen size (point) 4
- $0008 PnMode pen mode (word) 2
- $0009 PnPat pen pattern 8
- $000A FillPat fill pattern 8
- $000B OvSize oval size (point) 4
- $000C Origin dh, dv (word) 4
- $000D TxSize text size (word) 2
- $000E FgColor foreground color (long) 4
- $000F BkColor background color (long) 4
- $0010 TxRatio numer (point), denom (point) 8
- $0011 Version version (byte) 1
- $0012 *BkPixPat color background pattern variable:
- see Table 4
- $0013 *PnPixPat color pen pattern variable:
- see Table 4
- $0014 *FillPixPat color fill pattern variable:
- see Table 4
- $0015 *PnLocHFrac fractional pen position 2
- $0016 *ChExtra extra for each character 2
- $0017 *reserved for Apple use opcode 0
- $0018 *reserved for Apple use opcode 0
- $0019 *reserved for Apple use opcode 0
- $001A *RGBFgCol RGB foreColor variable:
- see Table 4
- $001B *RGBBkCol RGB backColor variable:
- see Table 4
- $001C *HiliteMode hilite mode flag 0
- $001D *HiliteColor RGB hilite color variable:
- see Table 4
- $001E *DefHilite Use default hilite color 0
- $001F *OpColor RGB OpColor for variable:
- arithmetic modes see Table 4
- $0020 Line pnLoc (point), newPt (point) 8
- $0021 LineFrom newPt (point) 4
- $0022 ShortLine pnLoc (point, dh, dv 6
- (-128..127)
- $0023 ShortLineFrom dh, dv (-128..127) 2
- $0024 *reserved for Apple use opcode + 2 bytes data 2+ data
- length + data length
- $0025 *reserved for Apple use opcode + 2 bytes data 2+ data
- length + data length
- $0026 *reserved for Apple use opcode + 2 bytes data 2+ data
- length + data length
- $0027 *reserved for Apple use opcode + 2 bytes data 2+ data
- length + data length
- $0028 LongText txLoc (point), count 5 + text
- (0..255), text
- $0029 DHText dh (0..255), count 2 + text
- (0..255), text
- $002A DVText dv (0..255), count 2 + text
- (0..255), text
- $002B DHDVText dh, dv (0..255), count 3 + text
- (0..255), text
- $002C *reserved for Apple use opcode + 2 bytes data 2+ data
- length + data length
- $002D *reserved for Apple use opcode + 2 bytes data 2+ data
- length + data length
- $002E *reserved for Apple use opcode + 2 bytes data 2+ data
- length + data length
- $002F *reserved for Apple use opcode + 2 bytes data 2+ data
- length + data length
- $0030 frameRect rect 8
- $0031 paintRect rect 8
- $0032 eraseRect rect 8
- $0033 invertRect rect 8
- $0034 fillRect rect 8
- $0035 *reserved for Apple use opcode + 8 bytes data 8
- $0036 *reserved for Apple use opcode + 8 bytes data 8
- $0037 *reserved for Apple use opcode + 8 bytes data 8
- $0038 frameSameRect rect 0
- $0039 paintSameRect rect 0
- $003A eraseSameRect rect 0
- $003B invertSameRect rect 0
- $003C fillSameRect rectangle 0
- $003D *reserved for Apple use opcode 0
- $003E *reserved for Apple use opcode 0
- $003F *reserved for Apple use opcode 0
- $0040 frameRRect rect (see Note # 5 ) 8
- $0041 paintRRect rect (see Note # 5 ) 8
- $0042 eraseRRect rect (see Note # 5 ) 8
- $0043 invertRRect rect (see Note # 5 ) 8
- $0044 fillRRect rect (see Note # 5 ) 8
- $0045 *reserved for Apple use opcode + 8 bytes data 8
- $0046 *reserved for Apple use opcode + 8 bytes data 8
- $0047 *reserved for Apple use opcode + 8 bytes data 8
- $0048 frameSameRRect rect 0
- $0049 paintSameRRect rect 0
- $004A eraseSameRRect rect 0
- $004B invertSameRRect rect 0
- $004C fillSameRRect rect 0
- $004D *reserved for Apple use opcode 0
- $004E *reserved for Apple use opcode 0
- $004F *reserved for Apple use opcode 0
- $0050 frameOval rect 8
- $0051 paintOval rect 8
- $0052 eraseOval rect 8
- $0053 invertOval rect 8
- $0054 fillOval rect 8
- $0055 *reserved for Apple use opcode + 8 bytes data 8
- $0056 *reserved for Apple use opcode + 8 bytes data 8
- $0057 *reserved for Apple use opcode + 8 bytes data 8
- $0058 frameSameOval rect 0
- $0059 paintSameOval rect 0
- $005A eraseSameOval rect 0
- $005B invertSameOval rect 0
- $005C fillSameOval rect 0
- $005D *reserved for Apple use opcode 0
- $005E *reserved for Apple use opcode 0
- $005F *reserved for Apple use opcode 0
- $0060 frameArc rect, startAngle, arcAngle 12
- $0061 paintArc rect, startAngle, arcAngle 12
- $0062 eraseArc rect, startAngle, arcAngle 12
- $0063 invertArc rect, startAngle, arcAngle 12
- $0064 fillArc rect, startAngle, arcAngle 12
- $0065 *reserved for Apple use opcode + 12 bytes 12
- $0066 *reserved for Apple use opcode + 12 bytes 12
- $0067 *reserved for Apple use opcode + 12 bytes 12
- $0068 frameSameArc rect 4
- $0069 paintSameArc rect 4
- $006A eraseSameArc rect 4
- $006B invertSameArc rect 4
- $006C fillSameArc rect 4
- $006D *reserved for Apple use opcode + 4 bytes 4
- $006E *reserved for Apple use opcode + 4 bytes 4
- $006F *reserved for Apple use opcode + 4 bytes 4
- size
- $0070 framePoly poly polygon
- size
- $0071 paintPoly poly polygon
- size
- $0072 erasePoly poly polygon
- size
- $0073 invertPoly poly polygon
- size
- $0074 fillPoly poly polygon
- size
- $0075 *reserved for Apple use opcode + poly
- $0076 *reserved for Apple use opcode + poly
- $0077 *reserved for Apple use opcode word + poly
- $0078 frameSamePoly (not yet implemented: 0
- same as 70, etc)
- $0079 paintSamePoly (not yet implemented) 0
- $007A eraseSamePoly (not yet implemented) 0
- $007B invertSamePoly (not yet implemented) 0
- $007C fillSamePoly (not yet implemented) 0
- $007D *reserved for Apple use opcode 0
- $007E *reserved for Apple use opcode 0
- $007F *reserved for Apple use opcode 0
- $0080 frameRgn rgn region size
- $0081 paintRgn rgn region size
- $0082 eraseRgn rgn region size
- $0083 invertRgn rgn region size
- $0084 fillRgn rgn region size
- $0085 *reserved for Apple use opcode + rgn region size
- $0086 *reserved for Apple use opcode + rgn region size
- $0087 *reserved for Apple use opcode + rgn region size
- $0088 frameSameRgn (not yet implemented: 0
- same as 80, etc.)
- $0089 paintSameRgn (not yet implemented) 0
- $008A eraseSameRgn (not yet implemented) 0
- $008B invertSameRgn (not yet implemented) 0
- $008C fillSameRgn (not yet implemented) 0
- $008D *reserved for Apple use opcode 0
- $008E *reserved for Apple use opcode 0
- $008F *reserved for Apple use opcode 0
- $0090 *BitsRect copybits, rect clipped variable:
- see Table 4
- $0091 *BitsRgn copybits, rgn clipped variable:
- see Table 4
- $0092 *reserved for Apple use opcode + 2 bytes data 2+ data
- length + data length
- $0093 *reserved for Apple use opcode + 2 bytes data 2+ data
- length + data length
- $0094 *reserved for Apple use opcode + 2 bytes data 2+ data
- length + data length
- $0095 *reserved for Apple use opcode + 2 bytes data 2+ data
- length + data length
- $0096 *reserved for Apple use opcode + 2 bytes data 2+ data
- length + data length
- $0097 *reserved for Apple use opcode word + 2 bytes 2+ data
- data length + data length
- $0098 *PackBitsRect packed copybits, rect variable:
- clipped see Table 4
- $0099 *PackBitsRgn packed copybits, rgn variable:
- clipped see Table 4
- $009A *reserved for Apple use opcode + 2 bytes data 2+ data
- length + data length
- $009B *reserved for Apple use opcode + 2 bytes data 2+ data
- length + data length
- $009C *reserved for Apple use opcode + 2 bytes data 2+ data
- length + data length
- $009D *reserved for Apple use opcode + 2 bytes data 2+ data
- length + data length
- $009E *reserved for Apple use opcode + 2 bytes data 2+ data
- length + data length
- $009F *reserved for Apple use opcode + 2 bytes data 2+ data
- length + data length
- $00A0 ShortComment kind (word) 2
- $00A1 LongComment kind (word), size 4+data
- (word), data
- $00A2 *reserved for Apple use opcode + 2 bytes data 2+ data
- length + data length
- : : :
- : : :
- $00AF *reserved for Apple use opcode + 2 bytes data 2+ data
- length + data length
- $00B0 *reserved for Apple use opcode 0
- : : :
- : : :
- $00CF *reserved for Apple use opcode 0
- $00D0 *reserved for Apple use opcode + 4 bytes data 4+ data
- length + data length
- : : :
- : : :
- $00FE *reserved for Apple use opcode + 4 bytes data 4+ data
- length + data length
- $00FF opEndPic end of picture 2
- $0100 *reserved for Apple use opcode + 2 bytes data 2
- : : :
- : : :
- $01FF *reserved for Apple use opcode + 2 bytes data 2
- $0200 *reserved for Apple use opcode + 4 bytes data 4
- : : :
- $0BFF *reserved for Apple use opcode + 4 bytes data 22
- $0C00 HeaderOp opcode 24
- $0C01 *reserved for Apple use opcode + 4 bytes data 24
- : : :
- $7F00 *reserved for Apple use opcode + 254 bytes data 254
- : : :
- $7FFF *reserved for Apple use opcode + 254 bytes data 254
- $8000 *reserved for Apple use opcode 0
- : : :
- $80FF *reserved for Apple use opcode 0
- $8100 *reserved for Apple use opcode + 4 bytes data 4+ data
- length + data length
- : : :
- $FFFF *reserved for Apple use opcode + 4 bytes data 4+ data
- length + data length
- _______________________________________________________________________________
-
- Notes to Table 3
-
- 1. The opcode value has been extended to a word for version 2 pictures.
- Remember, opcode size = 1 byte for version 1.
- 2. Because opcodes must be word aligned in version 2 pictures, a byte
- of 0 (zero) data is added after odd-size data.
- 3. The size of reserved opcodes has been defined. They can occur only
- in version 2 pictures.
- 4. All unused opcodes are reserved for future Apple use and should
- not be used.
- 5. For opcodes $0040–$0044: rounded-corner rectangles use the setting
- of the ovSize point (refer to opcode $000B)
- 6. For opcodes $0090 and $0091: data is unpacked. These opcodes can
- only be used for rowbytes less than 8.
- 7. For opcodes $0100–$7FFF: the amount of data for opcode
- $nnXX = 2 * nn bytes.
-
- _______________________________________________________________________________
-
- »The New Opcodes: Expanded Format
-
- The expanded format of the version 2 PICT opcodes is shown in Table 4 below.
-
- Table 4–Data Format of Version 2 PICT Opcodes
- _______________________________________________________________________________
- Opcode Name Description Reference to Notes
-
- $0012 BkPixPat color background pattern See Note 1
- $0013 PnPixPat color pen pattern See Note 1
- $0014 FillPixPat color fill pattern See Note 1
- $0015 PnLocHFrac fractional pen If pnLocHFrac <> 1/2, it
- position (word) is always put to the
- picture before each
- text drawing operation.
-
- $0016 ChExtra extra for each After chExtra changes,
- character (word) it is put to picture
- before next text
- drawing operation.
- $001A RGBFgCol RGB foreColor (RBGColor) desired RGB for
- foreground
- $001B RGBBkCol RGB backColor (RGBColor) desired RGB for
- background
- $001D HiliteColor RGB hilite color
- $001F OpColor RGB OpColor for
- arithmetic modes
- $001C HiliteMode hilite mode flag No data; this opcode is
- sent before a drawing
- operation that uses the
- hilite mode.
- $001E DefHilite Use default hilite No data; set hilite
- color to default (from low
- memory).
- $0090 BitsRect copybits, rect See Note 2,4,5
- clipped
- $0091 BitsRgn copybits, rgn See Note 3,4,5
- clipped
- $0098 PackBitsRect packed copybits, See Note 2,4
- rect clipped
- $0099 PackBitsRgn packed copybits, See Note 3,4
- rgn clipped
- _______________________________________________________________________________
-
- Notes to Table 4
-
- 1. if patType = ditherPat
- then
- PatType: word; {pattern type = 2}
- Pat1Data: Pattern; {old pattern data}
- RGB: RGBColor; {desired RGB for pattern}
- else
- PatType: word; {pattern type = 1}
- Pat1Data: Pattern; {old pattern data}
- pixMap: {described in Table 5}
- colorTable: {described in Table 5}
-
- pixData: {described in Table 5}
- end;
-
- 2. pixMap: {described in Table 5}
- colorTable: {described in Table 5}
- srcRect: Rect; {source rectangle}
- dstRect: Rect; {destination rectangle}
- mode: Word; {transfer mode (may include new transfer }
- { modes)}
- PixData: {described in Table 5}
-
- 3. pixMap: {described in Table 5 }
- colorTable: {described in Table 5 }
- srcRect: Rect; {source rectangle}
- dstRect: Rect; {destination rectangle}
- mode: Word; {transfer mode (may include new transfer }
- { modes)}
- maskRgn: Rgn; {region for masking}
- PixData: {described in Table 5}
-
- 4. These four opcodes ($0090, $0091, $0098, $0099) are modifications of
- existing (version 1) opcodes. The first word following the opcode is
- the rowBytes. If the high bit of the rowBytes is set, then it is a
- pixMap containing multiple bits per pixel; if it is not set, it is a
- bitMap containing one bit per pixel. In general, the difference between
- version 1 and version 2 formats is that the pixMap replaces the bitMap,
- a color table has been added, and pixData replaces the bitData.
-
- 5. Opcodes $0090 and $0091 are used only for rowbytes less than 8.
-
- Table 5–Data Types Found Within New PICT Opcodes Listed in Table 4
- _______________________________________________________________________________
- Data Type Field Definitions Comments
-
- pixMap = baseAddr: long; {unused = 0}
- rowBytes: word; {rowBytes w/high byte set}
- Bounds: rect; {bounding rectangle}
- version: word; {version number = 0}
- packType: word; {packing format = 0}
- packSize: long; {packed size = 0}
- hRes: fixed; {horizontal resolution (default = }
- { $0048.0000)}
- vRes: fixed; {vertical resolution (default= }
- { $0048.0000)}
- pixelType: word; {chunky format = 0}
- pixelSize: word; {# bits per pixel (1,2,4,8)}
- cmpCount: word; {# components in pixel = 1}
- cmpSize: word; {size of each component = pixelSize }
- { for chunky}
- planeBytes: long; {offset to next plane = 0}
- pmTable: long; {color table = 0}
- pmReserved: long; {reserved = 0}
- end;
-
- colorTable = ctSeed: long; {id number for color table = 0}
- ctFlags: word; {flags word = 0}
- ctSize: word; {number of ctTable entries-1 }
- { ctSize + 1 color table entries }
- { each entry = pixel value, red, }
- { green, blue: word}
- end;
-
- pixData: {the following pseudocode describes the pixData data type}
- If rowBytes < 8 then data is unpacked
- data size = rowBytes*(bounds.bottom-bounds.top);
- If rowBytes >= 8 then data is packed.
- Image contains (bounds.bottom-bounds.top) packed scanlines.
- Packed scanlines are produced by the PackBits routine.
- Each scanline consists of [byteCount] [data].
- If rowBytes > 250 then byteCount is a word,
- else it is a byte.
- end;
- _______________________________________________________________________________
-
-
- æKY Summary…of…Color…QuickDraw
- æC »SUMMARY OF COLOR QUICKDRAW ColorQuickDraw
- _______________________________________________________________________________
-
- Constants
-
- CONST
- { Old-style grafPort colors }
-
- blackColor = 33;
- whiteColor = 30;
- redColor = 209;
- greenColor = 329;
- blueColor = 389;
- cyanColor = 269;
- magentaColor = 149;
- yellowColor = 89;
-
- { Arithmetic transfer modes }
-
- blend = 32;
- addPin = 33;
- addOver = 34;
- subPin = 35;
- adMax = 37;
- subOver = 38;
- adMin = 39;
-
- { Transparent mode constant }
-
- transparent = 36;
-
- { Text mask constant }
-
- mask = 64;
-
- { Highlight constants }
-
- hilite = 50;
- pHiliteBit = 0; {this is the correct value for use when }
- { calling the BitClear trap. BClr must use }
- { the assembly language equate hiliteBit}
-
- { Constant for resource IDs }
-
- defQDColors = 127;
-
- _______________________________________________________________________________
-
- Data Types
-
- TYPE
- RGBColor = RECORD
- red: INTEGER; {red component}
- green: INTEGER; {green component}
- blue: INTEGER {blue component}
- END;
-
- ColorSpec = RECORD
- value: INTEGER; {index or other value}
- rgb: RGBColor {true color}
- END;
-
- cSpecArray : ARRAY [0..0] of ColorSpec;
-
- CTabHandle = ^CTabPtr;
- CTabPtr = ^ColorTable;
- ColorTable = RECORD
- ctSeed: LONGINT; {unique identifier from table}
- ctFlags: INTEGER; {high bit is 1 for device, 0 }
- { for pixMap}
- ctSize: INTEGER; {number of entries -1 in }
- { ctTable}
- ctTable: cSpecArray
- END;
-
- CGrafPtr = ^CGrafPort;
- CGrafPort = RECORD
- device: INTEGER; {device ID for font selection}
- portPixMap: PixMapHandle; {port's pixel map}
- portVersion: INTEGER; {highest 2 bits always set}
- grafVars: Handle; {handle to more fields}
- chExtra: INTEGER; {extra characters placed}
- { on the end of a string}
- pnLocHFrac: INTEGER; {pen fraction}
- portRect: Rect; {port rectangle}
- visRgn: RgnHandle; {visible region}
- clipRgn: RgnHandle; {clipping region}
- bkPixPat: PixPatHandle; {background pattern}
- rgbFgColor: RGBColor; {requested foreground color}
- rgbBkColor: RGBColor; {requested background color}
- pnLoc: Point; {pen location}
- pnSize: Point; {pen size}
- pnMode: INTEGER; {pen transfer mode}
- pnPixPat: PixPatHandle; {pen pattern}
- fillPixPat: PixPatHandle; {fill pattern}
- pnVis: INTEGER; {pen visibility}
- txFont: INTEGER; {font number for text}
- txFace: Style; {text's character style}
- txMode: INTEGER; {text's transfer mode}
- txSize: INTEGER; {font size for text}
- spExtra: Fixed; {extra space}
- fgColor: LONGINT; {actual foreground color}
- bkColor: LONGINT; {actual background color}
- colrBit: INTEGER; {plane being drawn}
- patStretch: INTEGER; {used internally}
- picSave: Handle; {picture being saved}
- rgnSave: Handle; {region being saved}
- polySave: Handle; {polygon being saved}
- grafProcs: CQDProcsPtr {low-level drawing routines}
- END;
-
- GrafVars = RECORD
- rgbOpColor: RGBColor; {color for addPin, }
- { subPin, and blend}
- rgbHiliteColor: RGBColor; {color for hiliting}
- pmFgColor: Handle; {palette handle for }
- { foreground color}
- pmFgIndex: INTEGER; {index value for foreground}
- pmBkColor: Handle; {palette handle for }
- { background color}
- pmBkIndex: INTEGER; {index value for background}
- pmFlags: INTEGER; {flags for Palette Manager}
- END;
-
- PixMapHandle = ^PixMapPtr;
- PixMapPtr = ^PixMap;
- PixMap = RECORD
- baseAddr: Ptr; {pointer to pixMap data}
- rowBytes: INTEGER; {offset to next row}
- bounds: Rect; {boundary rectangle}
- pmVersion: INTEGER; {color QuickDraw version number}
- packType: INTEGER; {packing format}
- packSize: LONGINT; {size of data in packed state}
- hRes: Fixed; {horizontal resolution}
- vRes: Fixed; {vertical resolution}
- pixelType: INTEGER; {format of pixel image}
- pixelSize: INTEGER; {physical bits per pixel}
- cmpCount: INTEGER; {logical components per pixel}
- cmpSize: INTEGER; {logical bits per component}
- planeBytes: LONGINT; {offset to next plane}
- pmTable: CTabHandle; {absolute colors for this image}
- pmReserved: LONGINT {reserved for future expansion}
- END;
-
- PixPatHandle = ^PixPatPtr;
- PixPatPtr = ^PixPat;
- PixPat = RECORD
- patType: INTEGER; {pattern type}
- patMap: PixMapHandle; {pattern characteristics}
- patData: Handle; {pixel image defining pattern}
- patXData: Handle; {expanded pixel image}
- patXValid: INTEGER; {flags for expanded pattern data}
- patXMap: Handle; {handle to expanded pattern data}
- pat1Data: Pattern; {old-style pattern/RGB color}
- END;
-
- CCrsrHandle = ^CCrsrPtr;
- CCrsrPtr = ^CCrsr;
- CCrsr = RECORD
- crsrType: INTEGER; {type of cursor}
- crsrMap: PixMapHandle; {the cursor's pixMap}
- crsrData: Handle; {cursor's data}
- crsrXData: Handle; {expanded cursor data}
- crsrXValid: INTEGER; {depth of expanded data}
- crsrXHandle: Handle; {reserved for future use}
- crsr1Data: Bits16; {one-bit cursor}
- crsrMask: Bits16; {cursor's mask}
- crsrHotSpot: Point; {cursor's hotspot}
- crsrXTable: LONGINT; {private}
- crsrID: LONGINT; {ctSeed for expanded cursor}
- END;
-
- CIconHandle = ^CIconPtr;
- CIconPtr = ^CIcon;
- CIcon = RECORD
- iconPMap: PixMap; {the icon's pixMap}
- iconMask: BitMap; {the icon's mask bitMap}
- iconBMap: BitMap; {the icon's bitMap}
- iconData: Handle; {the icon's data}
- iconMaskData: ARRAY[0..0] OF INTEGER; {icon's }
- { mask and bitMap data}
- END;
-
- MatchRec = RECORD
- red: INTEGER; {red component}
- green: INTEGER; {green component}
- blue: INTEGER; {blue component}
- matchData: LONGINT;
- END;
-
- CQDProcsPtr = ^CQDProcs
- CQDProcs = RECORD
- textProc: Ptr;
- lineProc: Ptr;
- rectProc: Ptr;
- rRectProc: Ptr;
- ovalProc: Ptr;
- arcProc: Ptr;
- polyProc: Ptr;
- rgnProc: Ptr;
- bitsProc: Ptr;
- commentProc: Ptr;
- txMeasProc: Ptr;
- getPicProc: Ptr;
- putPicProc: Ptr;
- opcodeProc: Ptr; {fields added to QDProcs}
- newProc1: Ptr; {reserved for future use}
- newProc2: Ptr; {reserved for future use}
- newProc3: Ptr; {reserved for future use}
- newProc4: Ptr; {reserved for future use}
- newProc5: Ptr; {reserved for future use}
- newProc6: Ptr; {reserved for future use}
- END;
-
- _______________________________________________________________________________
-
- Routines
-
- Operations on cGrafPorts
-
- PROCEDURE OpenCPort (port: CGrafPtr);
- PROCEDURE InitCPort (port: CGrafPtr);
- PROCEDURE CloseCPort (port: CGrafPtr);
-
- Setting the Foreground and Background Colors
-
- PROCEDURE RGBForeColor (color : RGBColor);
- PROCEDURE RGBBackColor (color : RGBColor);
- PROCEDURE GetForeColor (VAR color : RGBColor);
- PROCEDURE GetBackColor (VAR color : RGBColor);
-
- Creating Pixel Maps
-
- FUNCTION NewPixMap : PixMapHandle;
- PROCEDURE DisposPixMap (pm: PixMapHandle);
- PROCEDURE CopyPixMap (srcPM,dstPM: PixMapHandle);
-
- Operations on Pixel Maps
-
- PROCEDURE CopyBits (srcBits, dstBits: BitMap; srcRect, dstRect: Rect;
- mode: INTEGER; maskRgn: RgnHandle);
- PROCEDURE CopyMask (srcBits,maskBits,dstBits: BitMap;
- srcRect, maskRect, dstRect: Rect);
- PROCEDURE SeedCFill (srcBits, dstBits: BitMap; srcRect, dstRect: Rect;
- seedH, seedV: INTEGER; matchProc: ProcPtr;
- matchData: LONGINT);
- PROCEDURE CalcCMask (srcBits, dstBits: BitMap; srcRect, dstRect: Rect;
- seedRGB: RGBColor; matchProc: ProcPtr; matchData: LONGINT);
-
- Operations on Pixel Patterns
-
- FUNCTION NewPixPat : PixPatHandle;
- PROCEDURE DisposPixPat (ppat: PixPatHandle);
- FUNCTION GetPixPat (patID: INTEGER): PixPatHandle;
- PROCEDURE CopyPixPat (srcPP,dstPP: PixPatHandle);
- PROCEDURE MakeRGBPat (ppat: PixPatHandle; myColor: RGBColor);
- PROCEDURE PenPixPat (ppat: PixPatHandle);
- PROCEDURE BackPixPat (ppat: PixPatHandle);
-
- Color Drawing Operations
-
- PROCEDURE FillCRect (r: Rect; ppat: PixPatHandle);
- PROCEDURE FillCOval (r: Rect; ppat: PixPatHandle);
- PROCEDURE FillCRoundRect (r: Rect; ovWd,ovHt: INTEGER; ppat: PixPatHandle);
- PROCEDURE FillCArc (r: Rect; startAngle,arcAngle: INTEGER;
- ppat: PixPatHandle);
- PROCEDURE FillCRgn (rgn: RgnHandle; ppat: PixPatHandle);
- PROCEDURE FillCPoly (poly: PolyHandle; ppat: PixPatHandle);
- PROCEDURE GetCPixel (h,v: INTEGER; VAR cPix: RGBColor);
- PROCEDURE SetCPixel (h,v: INTEGER; cPix: RGBColor);
-
- Operations on Color Cursors
-
- FUNCTION GetCCursor (crsrID: INTEGER): CCrsrHandle;
- PROCEDURE SetCCursor (cCrsr: CCrsrHandle);
- PROCEDURE DisposCCursor (cCrsr: CCrsrHandle);
- PROCEDURE AllocCursor;
-
- Operations on Icons
-
- FUNCTION GetCIcon (id: INTEGER): CIconHandle;
- PROCEDURE DisposCIcon (theIcon: CIconHandle);
- PROCEDURE PlotCIcon (theRect: Rect; theIcon: CIconHandle);
-
- Operations on cGrafPort Fields
-
- PROCEDURE SetPortPix (pm: PixMapHandle);
- PROCEDURE OpColor (color: RGBColor);
- PROCEDURE HiliteColor (color:RGBColor);
- PROCEDURE CharExtra (extra:Fixed);
- PROCEDURE SetStdCProcs (VAR cProcs: CQDProcs);
-
- Operations on Color Tables
-
- FUNCTION GetCTable (ctID: INTEGER): CTabHandle;
- PROCEDURE DisposCTable (ctTab: CTabHandle);
-
- Color Picture Operations
-
- FUNCTION OpenPicture (picFrame: Rect) : PicHandle;
-
- _______________________________________________________________________________
-
- Global Variables
-
- HiliteMode {if the hilite mode is set, highlighting is on}
- HiliteRGB {default highlight color for the system}
-
- _______________________________________________________________________________
-
- Assembly-Language Interface
-
- HiLite Constant
-
- hiliteBit EQU 7 ;flag bit in HiliteMode
- ; this is the correct value for use in assembler
- ; programs
-
- Equates for Resource IDs
-
- defQDColors EQU 127 ;resource ID of clut for default QDColors
-
- RGBColor structure
-
- red EQU $0 ;[word] red channel intensity
- green EQU $2 ;[word] green channel intensity
- blue EQU $4 ;[word] blue channel intensity
- rgbColor EQU $6 ;size of record
-
- ColorSpec structure
-
- value EQU $0 ;[short] value field
- rgb EQU $2 ;[rgbColor] rgb values
- colorSpecSize EQU $8 ;size of record
-
- Additional Offsets in a cGrafPort
-
- portPixMap EQU portBits ;[long] pixelMap handle
- portVersion EQU portPixMap+4 ;[word] port version number
- grafVars EQU portVersion+2 ;[long] handle to new fields
- chExtra EQU grafVars+4 ;[word] extra characters placed at
- ; the end of a string
- pnLocHFrac EQU chExtra+2 ;[word] pen fraction
-
- bkPixPat EQU bkPat ;[long] handle to bk pattern
- rgbFgColor EQU bkPixPat+4 ;[6 bytes] RGB components of fg color
- rgbBkColor EQU RGBFgColor+6 ;[6 bytes] RGB components of bk color
-
- pnPixPat EQU $3A ;[long] handle to pen's pattern
- fillPixPat EQU pnPixPat+4 ;[long] handle to fill pattern
-
- Offsets Within GrafVars
-
- rgbOpColor EQU 0 ;[6 bytes] color for addPin,
- ; subPin, and blend
- rgbHiliteColor EQU rgbOpColor+6 ;[6 bytes] color for hiliting
- pmFgColor EQU rgbHiliteColor+6 ;[4 bytes] Palette handle for
- ; foreground color
- pmFgIndex EQU pmFgColor+4 ;[2 bytes] index value for
- ; foreground
- pmBkColor EQU pmFgIndex+2 ;[4 bytes] Palette handle for
- ; background color
- pmBkIndex EQU pmBkColor+4 ;[2 bytes] index value for
- ; background
- pmFlags EQU pmBkIndex+2 ;[2 bytes] Flags for Palette
- ; manager
- grafVarRec EQU pmFlags+2 ;size of grafVar record
-
- PixMap field offsets
-
- pmBaseAddr EQU $0 ;[long]
- pmNewFlag EQU $4 ;[1 bit] upper bit of rowbytes is flag
- pmRowBytes EQU $4 ;[word]
- pmBounds EQU $6 ;[rect]
- pmVersion EQU $E ;[word] pixMap version number
- pmPackType EQU $10 ;[word] defines packing format
- pmPackSize EQU $12 ;[long] size of pixel data
- pmHRes EQU $16 ;[fixed] h. resolution (ppi)
- pmVRes EQU $1A ;[fixed] v. resolution (ppi)
- pmPixelType EQU $1E ;[word] defines pixel type
- pmPixelSize EQU $20 ;[word] # bits in pixel
- pmCmpCount EQU $22 ;[word] # components in pixel
- pmCmpSize EQU $24 ;[word] # bits per field
- pmPlaneBytes EQU $26 ;[long] offset to next plane
- pmTable EQU $2A ;[long] color map
- pmReserved EQU $2E ;[long] must be 0
- pmRec EQU $32 ; size of pixMap record
-
- PixPat field offsets
-
- patType EQU $0 ;[word] type of pattern
- patMap EQU $2 ;[long] handle to pixmap
- patData EQU $6 ;[long] handle to data
- patXData EQU $A ;[long] handle to expanded pattern data
- patXValid EQU $E ;[word] flags whether expanded pattern valid
- patXMap EQU $10 ;[long] handle to expanded pattern data
- pat1Data EQU $14 ;[8 bytes] old-style pattern/RGB color
- ppRec EQU $1C ; size of pixPat record
-
- Pattern Types
-
- oldPat EQU 0 ;foreground/background pattern
- newPat EQU 1 ;self-contained color pattern
- ditherPat EQU 2 ;rgb value to be dithered
- oldCrsrPat EQU $8000 ;old-style cursor
- CCrsrPat EQU $8001 ;new-style cursor
-
- CCrsr (Color Cursor) field offsets
-
- crsrType EQU 0 ;[word] cursor type
- crsrMap EQU crsrType+2 ;[long] handle to cursor's pixmap
- crsrData EQU crsrMap+4 ;[long] handle to cursor's color data
- crsrXData EQU crsrData+4 ;[long] handle to expanded data
- crsrXValid EQU crsrXData+4 ;[word] handle to expanded data (0 if none)
- crsrXHandle EQU crsrXValid+2 ;[long] handle for future use
- crsr1Data EQU crsrXHandle+4 ;[16 words] one-bit data
- crsrMask EQU crsr1Data+32 ;[16 words] one-bit mask
- crsrHotSpot EQU crsrMask+32 ;[point] hot-spot for cursor
- crsrXTable EQU crsrHotSpot+4 ;[long] private
- crsrID EQU crsrXTable+4 ;[long] color table seed for
- ; expanded cursor
- crsrRec EQU crsrID+4 ;size of cursor save area
-
- CIcon (Color Icon) field offsets
-
- iconPMap EQU 0 ;[pixmap] icon's pixMap
- iconMask EQU iconPMap+pmRec ;[bitmap] 1-bit version of icon
- ; 1-bit mask
- iconBMap EQU iconMask+bitmapRec ;[bitmap] 1-bit version of icon
- iconData EQU iconBMap+bitmapRec ;[long] Handle to pixMap data
- ; followed by bMap and mask data
- iconRec EQU iconData+4 ;size of icon header
-
- Extensions to the QDProcs record
-
- opcodeProc EQU $34 ;[pointer]
- newProc1 EQU $38 ;[pointer]
- newProc2 EQU $3C ;[pointer]
- newProc3 EQU $40 ;[pointer]
- newProc4 EQU $44 ;[pointer]
- newProc5 EQU $48 ;[pointer]
- newProc6 EQU $4C ;[pointer]
- cqdProcsRec EQU $50 ; size of QDProcs record
-
- MatchRec structure
-
- red EQU $0 ; [word] defined in RGBColor
- green EQU $2 ; [word] defined in RGBColor
- blue EQU $4 ; [word] defined in RGBColor
- matchData EQU $6 ; [long]
- matchRecSize EQU $A ;size of record
-
- Global Variables
-
- HiliteMode EQU $938 ;if the hilite bit is set, highlighting is on
- HiliteRGB EQU $DA0 ;default highlight color for the system
-
- Further Reference:
- _______________________________________________________________________________
- QuickDraw
- Graphics Devices
- Color Manager
- Color Picker Package
- Palette Manager
- Resource Manager
- Technical Note #21, QuickDraw’s Internal Picture Definition
- Technical Note #27, MacDraw’s PICT File Format
- Technical Note #120, Drawing Into an Off-Screen Pixel Map
- Technical Note #163, Adding Color With CopyBits
- Technical Note #171, _PackBits Data Format
- Technical Note #244, A Leading Cause of Color Cursor Cursing
- 32-Bit QuickDraw Documentation
-
- æKY CompatibilityGuidelines
- æC
- _______________________________________________________________________________
-
- COMPATIBILITY GUIDELINES
- _______________________________________________________________________________
-
- About…the…Compatibility…Guidelines…Vol…VI…Chapter
- About…Compatibility…Vol…VI
- Using…Memory…Wisely
- Using…Assembly…Language
- Accessing…Hardware
- Using…Low-Memory…Global…Variables
- Determining…Whether…a…Trap…Is…Available
- Running…in…System…Software…Version…7.0
- Allowing…Multiple…Applications
- Supporting…Standard…AppleEvents
- Selecting…AppleEvents…to…Support
- Isolating…User…Interface…Code
- Modifying…the…Event…Loop
- Indicating…an…Application…Is…AppleEvent-Aware
- Removing…Font…Size…Restrictions
- Operating…With…Virtual…Memory
- Localizing…Macintosh…Programs
- General…Guidelines…for…Compatibility
- Other…Localization…Tools
- Running…Macintosh…Programs…Under…A/UX
- How…the…A/UX…Toolbox…Works
- Using…the…A/UX…Toolbox
- A/UX…Compatibility…Guidelines
- About…the…Gestalt…Manager
- Using…the…Gestalt…Manager
- Determining…Features…of…the…Operating…Environment
- Determining…Whether…Gestalt…Is…Available
- Interpreting…Gestalt…Responses
- Interpreting…Responses…to…Environmental…Selectors
- Interpreting…Responses…to…Informational…Selectors
- Adding…Gestalt…Selectors
- Modifying…Gestalt…Selectors
- Specifying…Gestalt…Selector…Functions
- Gestalt…Manager…Routines
- Getting…Information…About…the…Operating…Environment
- Adding…Selector…Codes
- Modifying…Selector…Codes
- Summary…of…the…Gestalt…Manager
- Gestalt…Manager…Constants
- Gestalt…Manager…Routines…Summary
- Gestalt…Manager…Result…Codes
-
- About…The…CompatibilityGuide…Chapter
- Compatibility
- Determining…the…Features…of…a…Machine
- Localization
- Applications…in…a…Shared…Environment
- Summary…of…Compatability…Guidelines
- _______________________________________________________________________________
-
-
-
- æKY About…the…Compatibility…Guidelines…Vol…VI…Chapter
- æC »ABOUT THIS CHAPTER Compatibility Guidelines
- _______________________________________________________________________________
-
- This chapter describes how you can write applications that have the greatest
- chance of operating on all models of the Macintosh® computer, regardless of the
- hardware components found on any particular machine and of the available system
- software, managers, and device drivers. It addresses how you can take advantage
- of features that are new to system software version 7.0 in ways that are least
- likely to cause problems for users who are not running version 7.0. In a word,
- this chapter provides as much advice as possible to help you achieve maximum
- compatibility for your applications on all Macintosh computers, including those
- running version 7.0.
-
- System software version 7.0 provides the most important test of software
- compatibility since the introduction of the Macintosh II, and you must
- understand how you may need to revise your current applications so that they
- operate correctly with this new system software. Fortunately, if you have
- followed the guidelines given in previous volumes of Inside Macintosh, your
- applications stand a very good chance of working correctly in version 7.0
- without any modification whatsoever. However, version 7.0 introduces many new
- features and capabilities that you may wish to use in your applications, without
- sacrificing compatibility with earlier versions of system software. This chapter
- provides a number of additional guidelines to help you revise existing
- applications to take advantage of version 7.0 features while retaining
- compatibility with previous system software.
-
- System software version 7.0, with its multitasking environment and its new
- emphasis on communication and cooperation among applications, places certain
- responsibilities on applications. As a result, you must be more aware than ever
- of the programming shortcuts that can result in incompatibility.
-
- This chapter focuses on several aspects of writing software that is compatible
- with all Macintosh computers:
-
- • what can cause compatibility problems and how in general to avoid those
- problems
-
- • how to write applications that execute in both version 6.0 and version
- 7.0 system software
-
- • how to determine what software and hardware features are available on a
- particular machine
-
- • how to write applications that execute under A/UX®, Apple’s version of
- the UNIX® operating system
-
- • how to write software that can be easily modified for use in other
- countries
-
- This chapter also describes the Gestalt Manager, a set of three new Operating
- System functions that provide applications with a simple and efficient method
- for determining what software and hardware features are available on a given
- machine. You need to use the Gestalt Manager if your application takes advantage
- of particular hardware components (such as a floating-point unit) or software
- modules (such as Color QuickDraw™) that are not available on all Macintosh
- computers. Your application can also use the Gestalt Manager to inform the
- Operating System (and hence other applications) that it is present in the
- current environment.
-
- The Gestalt Manager is available in system software version 7.0. It is also
- included in system software versions 6.0.4 and 6.0.5, and in ROM on two
- machines, the Macintosh IIci and the Macintosh Portable. Your development system
- may supply code that allows you to call Gestalt on earlier system software
- versions; check the documentation provided with your development system to see
- if this is possible. Of course, since you cannot use Gestalt to determine if it
- is present, you must do that in some other way; one such method is illustrated
- in
- “Determining Whether Gestalt Is Available” later in this chapter.
-
- You need to read this chapter if you are interested in writing applications that
- execute on as many Macintosh computers as possible or under alternate operating
- systems such as A/UX. In particular, if you wish to enhance an existing product
- so that it supports new features of system software version 7.0 but also
- executes correctly in earlier versions of system software, or if you wish to
- write a new product that executes only in version 7.0, you should look at
- “Running In System Software Version 7.0.” You should read the sections on the
- Gestalt Manager later in this chapter if you need to take advantage of specific
- software or hardware features that may not be present on all versions of the
- Macintosh, or if you wish to inform other applications of the presence of your
- application in the operating environment.
-
- If you want your applications to run in system software versions earlier than
- 6.0.4 (where the Gestalt function is not available), you should be familiar with
- the Environs procedure, discussed in the Operating System Utilities chapter of
- Volumes II and IV, and the SysEnvirons function, discussed in the Compatibility
- Guidelines chapter of Volume V. Both Environs and SysEnvirons perform the kind
- of function that Gestalt performs—they allow you to determine what features are
- available on a specific machine. For reasons outlined later, however, you should
- not use either of these routines if the Gestalt function is available.
-
- Unfortunately, no single chapter can provide all the information you need to
- achieve the greatest possible compatibility for your applications. Most of the
- subsequent chapters in this volume (and indeed all previous volumes of Inside
- Macintosh) contain numerous warnings and guidelines that you should heed if you
- wish to increase the likelihood that your applications will execute correctly on
- all members of the Macintosh family and under alternate operating systems such
- as A/UX. The Memory Management chapter in this volume, for example, contains a
- fuller account of 32-bit clean programming than is given here and is essential
- reading for all developers. (An application is 32-bit clean if it can use all 32
- bits of a handle or pointer for memory addressing.) Similarly, the guidelines
- given in this chapter on writing A/UX-compatible Macintosh programs summarize
- and complement, but do not replace, the discussion in the separate publication
- A/UX Toolbox: Macintosh ROM Interface. So the complete story on Macintosh
- software compatibility does not end with this chapter, but it does begin here.
-
- _______________________________________________________________________________
-
- æKY About…Compatibility…Vol…VI
- æC »ABOUT COMPATIBILITY Compatibility Guidelines
- _______________________________________________________________________________
-
- Compatibility is the ability of a program to execute properly in different
- operating environments. Compatibility is important if you want to write software
- that runs, with little or no modification, on all members of the Macintosh
- family and in all system software versions. If you want to take advantage of
- particular software or hardware features that may not be present on all
- Macintosh computers, you need to know how to determine when those features are
- available.
-
- To appreciate why compatibility is a real and sometimes vexing concern, imagine
- that from all the Macintosh computers currently in operation in the world, you
- were to choose two at random. You would quite likely find a great number of
- differences in the hardware and software configurations on those two machines.
- You might find different CPUs, different memory management units (MMUs),
- different amounts of RAM, different shapes and sizes of monitors, and so forth.
- You are also likely to find different versions of system software, different ROM
- versions, different AppleTalk® drivers, different versions of managers,
- different printer interfaces, and so forth. Ideally, you want your product to
- run on both of those machines, regardless of the many significant differences
- between them. If you succeed in writing your application so that it does operate
- on both of those machines, you have succeeded in writing compatible software.
-
- This section provides a number of guidelines that you should follow if you want
- your applications to run on the greatest number of Macintosh computers. Some of
- these guidelines are quite general and apply to all programs; some apply only if
- you are programming in assembly language.
-
- One key to achieving compatibility is not to depend on things that may change.
- Inside Macintosh contains numerous warnings about which information is likely to
- change. As the Operating System and User Interface Toolbox evolve to accommodate
- the needs of developers and users, many of the elements will vary. Whenever
- possible, Apple strives to add features without altering existing interfaces. In
- general, you can assume that Operating System and Toolbox routines are less
- likely to change than data structures. Therefore, you should never manipulate
- data structures directly, even if their structure is documented. Instead, you
- should manipulate those structures only indirectly, by calling Operating System
- and Toolbox routines that achieve the desired effect. In particular, you should
- never alter any portion of a data structure marked as unused or reserved.
-
- Another key to writing compatible code is to code defensively. Do not assume
- that users perform actions in a particular order, and do not assume that
- function and procedure calls always succeed. You should always test the return
- values of routines for errors, as illustrated in most of the code samples
- presented in this volume.
-
- _______________________________________________________________________________
-
- æKY Using…Memory…Wisely
- æC »Using Memory Wisely Compatibility Guidelines
- _______________________________________________________________________________
-
- A major cause of compatibility problems, especially in connection with
- applications running in the A/UX operating system, is misuse of the Memory
- Manager . Here are some important points to keep in mind:
-
- • Do not set bits in master pointers directly. Use Memory Manager traps (for
- example, HLock) instead.
-
- • Always check the handle or pointer returned by a routine to make certain
- that it is not NIL. A NIL handle may indicate that a memory allocation
- failed, or that a requested resource could not be found.
-
- • Always check that a handle marked as purgeable has not been purged before
- using that handle. For example:
-
- IF myHandle^ <> NIL THEN {handle not purged}
-
- • Do not create your own handles; instead, use the Memory Manager function
- NewHandle.
-
- • Never make assumptions about the contents of Memory Manager data structures.
-
- If you have followed all these guidelines, it is likely that your application is
- 32-bit clean, that is, that it operates correctly in an environment where all 32
- bits of handles and pointers are used to store memory addresses. In system
- software version 7.0 and A/UX, your applications must be 32-bit clean or they
- may not operate correctly. See the Memory Management chapter in this volume for
- more information about these points.
-
- _______________________________________________________________________________
-
- æKY Using…Assembly…Language
- æC »Using Assembly Language Compatibility Guidelines
- _______________________________________________________________________________
-
- In general, your software should not include 68000 instructions that require the
- processor to be in supervisor mode; these include instructions that modify the
- contents of the Status Register (SR). Programmers typically modify the SR only
- as a means of changing the Condition Code Register (CCR) half of the SR; in
- these cases, an instruction that addresses the CCR directly will work instead.
- Do not use the User Stack Pointer or turn interrupts on and off.
-
- If you wish to handle your own exceptions (thereby relying on the position of
- data in the exception’s local stack frame), be aware that exception stack frames
- vary within the 68000 family.
-
- In particular, don’t use the TRAP instruction. Also, the TAS instruction, which
- uses a special read-modify-write memory cycle, is not supported by the Macintosh
- SE and Macintosh II hardware.
-
- A memory management unit available in some Macintosh computers may prevent code
- from writing to addresses within code segments. Also, the 68020 and 68030 cache
- code as it is encountered. You should allocate data blocks on the stack or in
- heap blocks separate from the code, and your code should not modify itself.
-
- _______________________________________________________________________________
-
- æKY Accessing…Hardware
- æC »Accessing Hardware Compatibility Guidelines
- _______________________________________________________________________________
-
- You should never address hardware directly; whenever possible, use the routines
- provided by the various device drivers and managers to send data to the
- available hardware. The addresses of memory-mapped hardware (like the VIA1,
- VIA2, SCC, and so forth) are always subject to change, as is the hardware
- itself. More important, direct access to such hardware is not possible in every
- operating environment. In multiuser systems like A/UX, for instance, the
- operating system manipulates all hardware; applications simply cannot write
- directly to hardware addresses.
-
- You should also avoid writing directly to the screen. Use QuickDraw routines
- whenever possible to draw on the screen. If you absolutely must write directly
- to the screen, do not assume that the screen is a fixed size or that it is in a
- fixed location. The location, size, and bit depth of the screen differ in
- various machines. Instead, you should read the QuickDraw global variable
- screenBits.bounds to determine the size of the screen, screenBits.baseAddr to
- determine the start of the screen, and screenBits.rowBytes to determine the
- offset between rows. On machines with Color QuickDraw, the device list
- (described in the Graphics Devices chapter in this volume) tells the location,
- size, and bit depth of each screen, screenBits contains the location and size of
- the main device, and GrayRgn contains a region describing the shape and size of
- the desktop.
-
- _______________________________________________________________________________
-
- æKY Using…Low-Memory…Global…Variables
- æC »Using Low-Memory Global Variables Compatibility Guidelines
- _______________________________________________________________________________
-
- Don’t rely on low-memory global variables. Many of these variables have been
- previously documented in Inside Macintosh, but many have not. In particular, you
- must avoid undocumented low-memory global variables, because they are most
- likely to change. But you should even avoid well-known global variables, since
- they may not be available in all environments or in the future. In general, you
- can avoid using low-memory global variables by using available routines that
- return the same information. For example, the TickCount function returns the
- same value that is contained in the low-memory global variable Ticks. TickCount
- is available under A/UX, but Ticks is not. So you can increase the likelihood of
- compatibility with A/UX by using the routine and not the global variable.
-
- _______________________________________________________________________________
-
- æKY Determining…Whether…a…Trap…Is…Available
- æC »Determining Whether a Trap Is Available Compatibility Guidelines
- _______________________________________________________________________________
-
- One important way that the Operating System and Toolbox have changed through
- successive versions of the ROM and system software is by the addition of
- numerous new traps. For example, the Time Manager released with system software
- version 7.0 includes a new trap, InsXTime, that provides certain improvements
- over the existing trap, InsTime. By using InsXTime instead of InsTime, your
- application can ensure that the periodic actions it requests will execute at a
- fixed frequency that does not drift over time. Before using a trap that is not
- available on all machines, however, you need to determine whether it is
- available; if you call InsXTime on a machine that does not implement it, your
- program will crash.
-
- Your application can check the availability of a particular trap such as
- InsXTime in one of two ways. First, you can call the Gestalt function that is
- discussed later in this chapter to see if the appropriate version of the
- corresponding driver or manager is available. For example, the trap InsXTime is
- included in the extended Time Manager but not in earlier versions of the Time
- Manager. So you could use Gestalt to determine which version of the Time Manager
- is available in the current operating environment. If Gestalt reports that the
- extended Time Manager is present, you can safely call InsXTime to queue your
- request.
-
- There are several cases, however, in which you cannot use Gestalt to determine
- whether a specific trap is implemented. You cannot, for instance, use Gestalt to
- determine whether the Gestalt trap itself is available. In addition, the trap
- whose existence you wish to test might not be included in any manager or, if it
- is, there might not be a Gestalt selector code for that manager. The
- WaitNextEvent trap is a good example of this: there is no way, using Gestalt, to
- determine whether WaitNextEvent is available.
-
- The second way to determine the availability of a particular Operating System or
- Toolbox trap is by testing directly for the existence of the trap, using the
- technique illustrated in Listing 3-1. You should use this method to test whether
- Gestalt is available before calling Gestalt. You should also use it to test for
- the existence of traps not included in managers or drivers about which Gestalt
- can report. This listing illustrates how to test the availability of
- WaitNextEvent.
-
- Listing 3-1. Determining whether a trap is available
-
- USES
- Types, Traps, OSUtils;
-
- FUNCTION NumToolboxTraps: Integer;
- BEGIN
- IF NGetTrapAddress(_InitGraf,ToolTrap) =
- NGetTrapAddress($AA6E,ToolTrap) THEN
- NumToolboxTraps := $200
- ELSE
- NumToolboxTraps := $400;
- END;
-
- FUNCTION GetTrapType(theTrap: Integer): TrapType;
- CONST
- TrapMask = $0800;
- BEGIN
- IF BAND(theTrap,TrapMask) > 0 THEN
- GetTrapType := ToolTrap
- ELSE
- GetTrapType := OSTrap;
- END;
-
- FUNCTION TrapAvailable(theTrap: Integer): Boolean;
- VAR
- tType: TrapType;
- BEGIN
- tType := GetTrapType(theTrap);
- IF tType = ToolTrap THEN BEGIN
- theTrap := BAND(theTrap, $07FF);
- IF theTrap >= NumToolboxTraps THEN
- theTrap := _Unimplemented;
- END;
- TrapAvailable := NGetTrapAddress(theTrap, tType) <>
- NGetTrapAddress(_Unimplemented, ToolTrap);
- END;
-
- FUNCTION WNEAvailable: Boolean;
- CONST
- _WaitNextEvent = $A860; {trap number of WaitNextEvent}
- BEGIN
- WNEAvailable := TrapAvailable(_WaitNextEvent);
- END;
-
- The NumToolboxTraps function relies on the fact that the InitGraf trap (trap
- number $A86E) is always implemented. If the trap dispatch table is large enough
- (that is, has more than $200 entries), then $AA6E always points to either
- Unimplemented or something else, but never to InitGraf. As a result, you can
- check the size of the trap dispatch table by checking to see if the address of
- trap $A86E is the same as $AA6E.
-
- The TrapAvailable function uses the information about the size of the dispatch
- table as follows: TrapAvailable first checks to see if the trap to be tested has
- a trap number greater than the total number of traps available on the machine.
- If so, then it sets theTrap to Unimplemented before testing it against the
- Unimplemented trap.
-
- Note: The technique presented in Listing 3-1 for determining whether a
- particular trap is available differs from techniques previously supported by
- Apple. The previous method determined the size of the trap dispatch table by
- checking the machine type. This type of check should not be used for any
- purposes other than simply displaying the information, as explained in “Using
- the Gestalt Manager.”
- _______________________________________________________________________________
-
- æKY Running…in…System…Software…Version…7.0
- æC »RUNNING IN SYSTEM SOFTWARE VERSION 7.0 Compatibility Guidelines
- _______________________________________________________________________________
-
- You should keep in mind the guidelines given in the previous sections whenever
- you are writing or revising any Macintosh application. If you heed those
- guidelines, you are likely to produce applications that run reasonably well in
- all environments, including system software version 7.0. So those guidelines
- define a minimal level of conformance necessary for your applications to run in
- version 7.0. Applications that conform to the programming interfaces documented
- in Inside Macintosh and that violate none of the guidelines presented earlier in
- this chapter are called 7.0-compatible because they run in version 7.0 without
- problems.
-
- An application can be 7.0-compatible, however, without taking advantage of the
- many new features available in system software version 7.0 and without
- exhibiting an awareness that other applications may be present and may wish to
- use processor time that would otherwise go unused. Among those that do take
- advantage of such features, there are at least two levels of involvement with
- version 7.0. An application is 7.0-friendly if it takes advantage of some of the
- special features of version 7.0 when executing under that environment, but is
- still able to perform all its principal functions when executing in version 6.0.
- An application is 7.0-dependent if it requires the existence of features that
- are available only in version 7.0; it might not even run in version 6.0. Even if
- 7.0-dependent applications do execute in version 6.0, they are virtually
- guaranteed to offer far fewer features there than in version 7.0. A good example
- of a 7.0-dependent application is a multimedia application that needs to do
- real-time mixing of multiple channels of stereo sound. The Sound Manager
- included with system software version 7.0 provides support for stereo output and
- the ability to mix multiple independent channels of sampled sound; neither of
- these features is available, however, with the Sound Manager provided with
- version 6.0 or earlier.
-
- The situation is similar to deciding whether your applications should use Color
- QuickDraw. If you revise existing black-and-white drawing programs to
- incorporate color, your applications operate either with or without Color
- QuickDraw. If you introduce new applications that require Color QuickDraw, they
- simply do not run on machines that don’t support color.
-
- The rest of this section gives guidelines on what you can do to existing
- applications to make them 7.0-friendly and not simply 7.0-compatible. The
- following pages describe in overview how to
-
- • be aware that the user may have launched multiple applications
-
- • support the minimal set of required AppleEvents™
-
- • remove font size restrictions to support outline fonts
-
- • make sure that your application operates correctly with virtual memory
-
- For complete details on any of these items, see the corresponding chapter in
- this volume. For example, to learn what you need to do to support outline fonts
- in your application, see the Font Manager chapter. (The information about
- cooperating with other open applications is found in the Event Manager chapter.)
-
- _______________________________________________________________________________
-
- æKY Allowing…Multiple…Applications
- æC »Allowing Multiple Applications Compatibility Guidelines
- _______________________________________________________________________________
-
- System software version 7.0 continues the development of the Macintosh Operating
- System into a multitasking environment in which multiple applications can be
- active and must share the available system resources. The facilities provided
- with earlier versions of system software by the optional MultiFinder™ package
- are now an integral part of system software version 7.0. This means that your
- application must display a certain awareness that other applications might be
- open at the same time and competing with it for processing time, memory, control
- of communications ports, and so forth.
-
- Although most operating systems regulate the sharing of available resources by
- having the system parcel them out, the Macintosh Operating System relies on the
- willingness of foreground and background applications to share those resources
- among themselves. For example, each application must determine its own memory
- requirements by specifying a minimum memory partition size (below which that
- application does not execute) and a preferred partition size (at which the
- application executes best). The Operating System itself has very little control
- over the partition size allotted to the application, other than by limiting that
- size to the available memory. Similarly, the Operating System has very little
- control over which applications receive processing time, since the user
- ultimately decides when to bring a background application into the foreground.
- If your application holds onto the microprocessor for too long while being
- switched into the background, other applications may appear sluggish and
- unresponsive.
-
- The lesson to be learned from all this is that, in system software version 7.0,
- your application must be a good neighbor. You cannot expect the Operating System
- to force responsible behavior on your application; rather, you must ensure that
- your application can happily coexist with other open applications by following
- these guidelines:
-
- • include a 'SIZE' resource that specifies reasonable minimum and preferred
- memory partition sizes; if you occasionally need larger amounts of
- memory, use the temporary memory routines described in the Memory
- Management chapter
-
- • use WaitNextEvent instead of GetNextEvent in your main event loop to
- obtain events from the Toolbox Event Manager; this allows other
- applications to use processor time your application doesn’t need, and
- allows your application to perform operations while it is in the
- background
-
- • modify your main event loop to process suspend and resume events; this
- reduces the time it takes to switch your application into the foreground
- or background
-
- For a more complete discussion of using WaitNextEvent and processing suspend and
- resume events, see the Event Manager chapter in this volume. That chapter also
- includes a description of the multitasking environment that is standard in
- system software version 7.0.
-
- _______________________________________________________________________________
-
- æKY Supporting…Standard…AppleEvents
- æC »Supporting Standard AppleEvents Compatibility Guidelines
- _______________________________________________________________________________
-
- Possibly the most significant new feature in system software version 7.0 is
- interapplication communication (IAC), which will play an increasingly important
- role in future versions of the Macintosh Operating System. One central part of
- IAC is the addition of high-level events to those events that the Event Manager
- receives and conveys to applications. High-level events allow applications to
- communicate with one another by putting events in the event queue of the
- receiving application.
-
- Apple has defined a standard set of such high-level events, known as
- AppleEvents, that are common to all or nearly all applications. Some AppleEvents
- must be supported by an application that supports any AppleEvents; these are
- known as required AppleEvents. With a minimal amount of work, you can modify
- your main event loop so it supports the required AppleEvents. In doing so, you
- increase the level of compatibility of your application and ease the transition
- to the days when applications expect other applications to support AppleEvents.
-
- There are four main steps you need to follow to incorporate support for the
- required AppleEvents into your application:
-
- 1. Identify the AppleEvents that you want your application to support.
-
- 2. Separate code that interacts with users from code that performs operations,
- whether requested by the user or by the required AppleEvents.
-
- 3. Modify the event loop to recognize the new type of event.
-
- 4. Inform the Operating System that your application can receive and act on the
- required AppleEvents.
-
- The following four sections provide further details on each of these steps. For
- a more complete story, see the Event Manager chapter in this volume.
-
- _______________________________________________________________________________
-
- æKY Selecting…AppleEvents…to…Support
- æC »Selecting AppleEvents to Support Compatibility Guidelines
- _______________________________________________________________________________
-
- First you need to identify the AppleEvents that you want your application to
- support. To make your application 7.0-friendly, you need to support the required
- AppleEvents that Apple Computer, Inc. has already defined. Table 3-1 lists the
- required AppleEvents, together with the parameters passed to the application
- with each kind of AppleEvent.
-
- Table 3-1. Required AppleEvents
-
- Event Parameters Description
- Open Application none open an application
- Open Documents list of documents open each specified document
- Print list of documents print each specified document
- Quit none terminate and exit the application
- Setup none update application’s menu items
- Get property return value of specified property
-
- Your application should already contain code to accomplish these standard
- operations. If so, you may still need to modify that code as described in the
- next section.
- _______________________________________________________________________________
-
- æKY Isolating…User…Interface…Code
- æC »Isolating User Interface Code Compatibility Guidelines
- _______________________________________________________________________________
-
- You need to separate code that interacts with users from code that actually
- performs the operations requested by the required AppleEvents. Generally, it is
- easy to mix user interface code with code that performs some operation, so you
- need to think carefully about this step. For example, many print loops have a
- section that begins like this:
-
- IF ( PrStlDialog(thePrRecHdl) ) THEN BEGIN
- IF ( PrJobDialog(thePrRecHdl) ) THEN BEGIN
- thePrPort := PrOpenDoc(thePrRecHdl, NIL, NIL);
- IF ( PrError = noErr ) THEN BEGIN
- PrOpenPage(thePrPort, NIL);
-
- Similarly, this fragment might execute when a user chooses Open from the File
- menu:
-
- IF SFGetFile(pt, str, fileFilter, numTypes,
- typeList, dlgHook, reply) THEN BEGIN
- err := FSOpen(reply.fName, reply.vRefNum, refNum);
-
- Since an AppleEvent (and not the user) might instruct your application to open
- or print a document, the application needs to be able to perform the requested
- operation without displaying the print or file dialog boxes. A way to do this in
- version 7.0 might go like this:
-
- FUNCTION PresentPrintDialogs: Boolean;
- VAR
- thePrRecHandle: THPrint;
- BEGIN
- PresentPrintDialogs := FALSE;
- IF ( PrStlDialog(thePrRecHdl) ) THEN
- IF ( PrJobDialog(thePrRecHdl) ) THEN
- PresentPrintDialogs := TRUE;
- END;
-
- PROCEDURE PrintDocument(thePrRecHdl: THPrint);
- VAR
- thePrPort: TPPrPort;
- BEGIN
- thePrPort := PrOpenDoc(thePrRecHdl, NIL, NIL);
- IF ( PrError = noErr ) THEN BEGIN
- PrOpenPage(thePrPort,NIL);
- ...
- END;
- END;
-
- In this way, your application can respond to print requests both from the user
- and from any AppleEvents it receives.
-
- _______________________________________________________________________________
-
- æKY Modifying…the…Event…Loop
- æC »Modifying the Event Loop Compatibility Guidelines
- _______________________________________________________________________________
-
- In system software version 7.0, the Event Manager manages three classes of
- events: low-level events (which are the traditional user-initiated events like
- mouse and keyboard events), operating system event (which inform applications of
- changes in their operating status), and high-level event (which include
- AppleEvents). AppleEvents are reported to an application using a new event type
- defined by the constant kHighLevelEvent.
-
- CONST kHighLevelEvent = 23;
-
- This means that you need to add a new selector to your branch statements.
- Listing 3-2 shows a simple event loop modified to accept AppleEvents.
-
- Listing 3-2. An event loop modified to receive high-level events
-
- PROCEDURE DoEvent(event: EventRecord);
- BEGIN
- CASE event.what OF
- nullEvent:
- DoIdle;
- mouseDown:
- DoMouseDown(event);
- mouseUp:
- DoMouseUp(event);
- keyDown, autoKey:
- DoKeyDown(event);
- activateEvt:
- DoActivate(event);
- updateEvt:
- DoUpdate(event);
- kOSEvent:
- DoOSEvent(event);
- kHighLevelEvent:
- DoHighLevelEvent(event);
- END;
- END; {DoEvent}
-
- At this point, you need to provide the DoHighLevelEvent routine to handle the
- AppleEvent (or other high-level event). Once you’ve separated the relevant
- user-interface part of your code, modified your event loop, and added a
- procedure that accepts high-level events, all you need to do is write a bit of
- code that knows how to look at AppleEvents and then calls the correct operation.
-
- _______________________________________________________________________________
-
- æKY Indicating…an…Application…Is…AppleEvent-Aware
- æC »Indicating an Application Is AppleEvent-Aware Compatibility Guidelines
- _______________________________________________________________________________
-
- The final thing you need to do is inform the Operating System that your
- application is able to receive and process AppleEvents. To accomplish this, you
- need to modify your application’s 'SIZE' resource, as explained in the Event
- Manager chapter.
-
- _______________________________________________________________________________
-
- æKY Removing…Font…Size…Restrictions
- æC »Removing Font Size Restrictions Compatibility Guidelines
- _______________________________________________________________________________
-
- System software version 7.0 introduces outline fonts, known as TrueType™. An
- outline font can be printed or displayed at any point size without the jagged
- appearance of some bitmapped fonts. A 7.0-friendly application should allow its
- users to take advantage of this improvement. Minimally, this means that users
- should be able to ask for any point size up to 32,768. Many applications now let
- users specify font sizes up to 127 point, but you should remove even this
- limitation when running in version 7.0. In addition, your application should
- allow users to increment or decrement the font size by 1 point.
-
- You can use the IsOutline routine, documented in the Font Manager chapter in
- this volume, to see if a particular font is an outline font. If it is, you might
- wish to indicate that fact in your font size menu. For example, suppose that
- your Size menu for a particular bitmapped font looks like the one in Figure 3-1.
-
- ø 3.1 Size menu for a bitmapped font
-
- To provide a visual indication that the selected font is an outline font that
- looks good at any size, you might change the menu to look like the one in Figure
- 3-2. One way to do this is by outlining all available sizes, as well as the
- Other item.
-
- ø 3.2 Size menu for an outline font
-
- The User Interface Guidelines chapter contains additional suggestions on
- incorporating outline fonts into your application.
-
- _______________________________________________________________________________
-
- æKY Operating…With…Virtual…Memory
- æC »Operating With Virtual Memory Compatibility Guidelines
- _______________________________________________________________________________
-
- System software version 7.0 supports virtual memory, a memory management scheme
- that extends the logical address space of the machine by using part of the
- available secondary storage (usually, a hard disk) to store parts of memory that
- are not currently in use. When virtual memory is present, the perceived amount
- of RAM can extend up to 14 megabytes on systems with 24-bit ROMs and up to 4
- gigabytes on systems with 32-bit clean ROMs. Since the Operating System has more
- addressable memory, your applications can ask for and receive larger blocks of
- memory than they would if virtual memory were not available.
-
- Virtual memory is available only on machines equipped with a memory management
- unit (MMU). Currently, these machines include 68030-based machines (where the
- MMU is built into the CPU) as well as 68020-based machines that contain the
- 68851 Paged Memory Management Unit. You can use the Gestalt function to
- determine whether virtual memory is installed. If it is, you may need to
- exercise caution to ensure that the normally invisible operation of virtual
- memory does not adversely affect the execution of your application. Applications
- that might need to be concerned with virtual memory include those that have
- critical timing requirements, execute code at interrupt time, or perform
- debugging operations.
-
- Note: The vast majority of applications do not need to know whether virtual
- memory is installed.
-
- One type of application that might need to know if virtual memory is operating
- is a multimedia application that manages very large images or incorporates many
- sounds into its presentations. Imagine that such an application wants to display
- a large number of intricate color images in rapid succession, and that some of
- those images are as large as a megabyte each. If virtual memory is operating, it
- is very likely that parts of those images are on disk when they need to be
- displayed. This means that in the middle of drawing a picture, the system has to
- stop long enough to read those parts of the picture off the disk. The result is
- that a noticeable delay may occur, which may be unacceptable.
-
- In a case like this, you can use routines that lock the appropriate data into
- RAM, so that displaying the image requires no disk access. These routines are
- fully documented in the Memory Management chapter later in this volume. Other
- software that may need to know about those routines includes drivers, interrupt
- code, and debugging applications.
-
- _______________________________________________________________________________
-
- æKY Localizing…Macintosh…Programs
- æC »LOCALIZING MACINTOSH PROGRAMS Compatibility Guidelines
- _______________________________________________________________________________
-
- Localization is the process of adapting an application to a specific language
- and country. By planning ahead and making localization relatively painless,
- you’ll ensure that international markets are available for your product in the
- future. This section provides a brief overview of what you need to do to make it
- easy to localize your application. For the complete account of writing software
- that is compatible with Macintosh computers throughout the world, you should
- read the TextEdit chapter and the Worldwide Software Overview later in this
- volume. You should also consult the “Developing Worldwide Software” section in
- the User Interface Guidelines chapter of this volume.
-
- _______________________________________________________________________________
-
- æKY General…Guidelines…for…Compatibility
- æC »General Guidelines Compatibility Guidelines
- _______________________________________________________________________________
-
- The key to easy localization is to store country-dependent information used by
- your application as resources (rather than within the application’s code). Text
- seen by the user can then be translated without modifying the code. In addition,
- storing such information in resources means that your application can be adapted
- for a different country simply by substituting the appropriate resources. Make
- sure that at least the following kinds of information are stored in resources:
-
- • all text, including special characters and delimiters
-
- • menus and keyboard equivalents for menu commands (if available)
-
- • character, word, phrase, and text translation tables
-
- • address formats, including zip codes and phone numbers
-
- When you create resources for your applications, remember the following key
- points:
-
- • text needs room to grow (up, down, and sideways)
-
- • translated text is often 50 percent larger than the U.S. English text
-
- • diacritical marks, widely used outside the United States, may extend up
- to the ascent line
-
- • some system fonts contain characters that extend to both the ascent and
- descent lines
-
- • potential grammar problems may arise from error messages, “natural”
- programming language structures, and so forth
-
- • text location within a window should be easy to change
- _______________________________________________________________________________
-
- æKY Other…Localization…Tools
- æC »Other Localization Tools Compatibility Guidelines
- _______________________________________________________________________________
-
- In addition to these general guidelines, you need to be aware of a host of other
- localization issues, such as differences in script systems and measurement
- systems. System software version 7.0 contains updated versions of several tools
- that you can use to facilitate localization of your applications—TextEdit, the
- International Utilities Package, and the Script Manager.
-
- Perhaps the most important localization tool is the Script Manager, which
- contains routines that allow your application to function correctly with
- non-Roman scripts (or writing systems). The Script Manager furnishes a standard
- interface that allows installation of different script systems, maintains global
- data structures, supports switching keyboards between different scripts, and
- provides a central dispatcher that gives your application access to script
- systems. It also contains utilities for text processing and parsing, which are
- useful for applications that do a lot of text manipulation. The Script Manager
- provides easy ways to translate your application into another writing system and
- to coordinate with the International Utilities Package.
-
- The International Utilities Package provides routines for dealing with sorting,
- currency, measurement systems, and date and time formatting. These tend to vary
- in some degree from script to script, language to language, and country to
- country, and your application should take advantage of the Macintosh Operating
- System’s ability to present this information in the correct format. It is
- important that you use the routines in this package rather than the System
- Utility routines contained in ROM; the ROM routines are not as accurate and
- (because they are used by the File Manager) cannot be localized for different
- countries.
-
- TextEdit provides routines that handle basic text formatting and editing
- capabilities, such as inserting new text or scrolling text within a window. The
- version of TextEdit included in system software version 7.0 contains new
- features that allow it to work with different scripts. For example, TextEdit 3.0
- takes advantage of the Script Manager’s handling of double-byte characters to
- display scripts (such as Kanji) with improved accuracy and consistency.
-
- For more information about the enhanced versions of TextEdit, see the TextEdit
- chapter in this volume. For complete information on both the International
- Utilities Package and the Script Manager, see the Worldwide Software Overview
- chapter.
-
- _______________________________________________________________________________
-
- æKY Running…Macintosh…Programs…Under…A/UX
- æC »RUNNING MACINTOSH PROGRAMS UNDER A/UX Compatibility Guidelines
- _______________________________________________________________________________
-
- A/UX is Apple’s version of the UNIX operating system, which provides a
- multitasking and multiuser software execution environment. One of the most
- distinctive features of A/UX in comparison with other implementations of the
- UNIX operating system is its ability to run conforming Macintosh applications.
- Within limits described later in this section, applications developed for the
- Macintosh Operating System using the standard Macintosh User Interface Toolbox
- routines will execute under A/UX. Figure 3-3 shows a typical screen under A/UX.
-
- ø 3.3 The Macintosh User Interface Under A/UX
-
- The ability to run Macintosh applications under A/UX is provided by enhancements
- to the A/UX kernel and by a library of functions known as the A/UX Toolbox. The
- A/UX Toolbox is a library of routines that enables a program running under A/UX
- to call Macintosh Toolbox routines and native Macintosh Operating System
- routines. The A/UX Toolbox provides a bridge between the Macintosh and A/UX
- environments, giving you two kinds of code compatibility:
-
- • You can execute Macintosh binary code (applications compiled in the
- Macintosh environment) under A/UX, within the current limitations of the
- A/UX Toolbox.
-
- • You can write common source code that can be separately built (that is,
- compiled and linked) into executable code for both environments.
-
- The A/UX Toolbox operates transparently to the user and to the application
- developer. This means that (subject once again to qualifications detailed later)
- your applications developed for the Macintosh Operating System should execute
- under the A/UX operating system.
-
- The version of A/UX currently available is A/UX Release 2.0, which greatly
- extends the capabilities of earlier versions. Release 2.0 supports more managers
- and drivers than previous versions, thereby increasing the level of
- compatibility with Macintosh applications. There is now transparent access to
- Macintosh file systems from within A/UX, so users no longer have to transfer
- files between the two systems manually.
-
- This section briefly explains how the A/UX Toolbox works and then provides
- details on writing Macintosh applications that execute under the A/UX operating
- system. A/UX Release 2.0 provides such a high level of compatibility with
- Macintosh applications that your existing applications may very well run under
- A/UX with no changes whatsoever. To run successfully under A/UX Release 2.0,
- your application should
-
- • be compatible with MultiFinder
-
- • be 32-bit clean (that is, operate in an environment where all 32 bits of
- a handle or pointer are significant in determining memory addresses)
-
- • use the Gestalt Manager to determine whether the appropriate versions of
- managers are present in the current operating environment
-
- • avoid reading or writing low-memory global variables
-
- In general, applications that conform to the interfaces documented in Inside
- Macintosh, are MultiFinder-aware, do not rely on low-memory global variables,
- and heed the various guidelines presented in “About Compatibility” should
- operate under A/UX.
-
- _______________________________________________________________________________
-
- æKY How…the…A/UX…Toolbox…Works
- æC »How the A/UX Toolbox Works Compatibility Guidelines
- _______________________________________________________________________________
-
- The primary function of the A/UX Toolbox is to make available to programs
- running under A/UX the standard Macintosh support code described in Inside
- Macintosh. Most of the support code consists of routines built into the
- Macintosh ROM.
-
- The ROM routines fall into two categories, User Interface Toolbox routines and
- Macintosh Operating System routines. The A/UX Toolbox uses one of two strategies
- for supporting a Macintosh ROM call, depending on whether the call is to the
- User Interface Toolbox or to the native Macintosh Operating System.
-
- When an A/UX Toolbox application calls one of the Macintosh User Interface
- Toolbox routines, the A/UX Toolbox intercepts the call and, if necessary,
- translates the parameters into a form usable by the ROM. After the A/UX Toolbox
- performs the translation, it invokes the ROM code that would be used in the
- native Macintosh environment.
-
- When an A/UX Toolbox application calls one of the Macintosh Operating System
- routines, the A/UX Toolbox diverts the call to a substitute routine in its own
- library. The A/UX Toolbox Operating System routines call the standard A/UX
- libraries to perform the A/UX equivalents of the Macintosh Operating System
- functions. The Macintosh Operating System ROM code is never used under A/UX.
- Note that some of the built-in User Interface Toolbox routines generate calls to
- the Macintosh Operating System routines; these calls are also intercepted by the
- A/UX Toolbox and diverted to routines in its own library.
-
- Figure 3-4 illustrates how the two elements of the A/UX Toolbox library interact
- with the application and the ROM code.
-
- ø 3.4 Interactions among applications, the A/UX Toolbox, and ROM code
-
- _______________________________________________________________________________
-
- æKY Using…the…A/UX…Toolbox
- æC »Using the A/UX Toolbox Compatibility Guidelines
- _______________________________________________________________________________
-
- The primary limitation on Macintosh applications running under A/UX is that the
- A/UX Toolbox does not currently support all managers and drivers. Table 3-2
- summarizes the status of various ROM libraries in A/UX Release 2.0.
-
- Table 3-2. Status of User Interface Toolbox and Macintosh Operating System
- libraries in the A/UX Toolbox
-
- ROM Library Implementation
-
- Alias Manager None
- Apple Desktop Bus None
- Binary-Decimal Conversion Package Full
- Color Manager Full
- Color Picker Package Full
- Color QuickDraw Full
- Control Manager Full
- Database Access Manager None
- Deferred Task Manager None
- Desk Manager Full
- Device Manager Full
- Dialog Manager Full
- Disk Driver Full
- Disk Initialization Package Full
- Edition Manager None
- Event Manager, Operating System Partial
- Event Manager, Toolbox Full*
- File Manager Full
- Floating Point Arithmetic
- and Transcendental Functions Packages Full*
- Font Manager Full
- Gestalt Manager Full
- Help Manager None
- International Utilities Package Full
- List Manager Package Full
- Memory Manager Full
- Menu Manager Full
- Notification Manager Full
- Package Manager Full
- Palette Manager Full
- Power Manager None
- PPC Toolbox None
- Printing Manager Full
- QuickDraw Full
- Resource Manager Full
- Scrap Manager Full
- Script Manager Full
- SCSI Manager None
- Segment Loader Partial
- Serial Driver Full
- Shutdown Manager Full*
- Slot Manager Full
- Sound Manager Full
- Startup Manager Full
- Standard File Package Full
- System Error Handler Full*
- TextEdit Full
- Time Manager Full*
- Utilities, Operating System Partial
- Utilities, Toolbox Full
- Vertical Retrace Manager Partial
- Window Manager Full
-
- Note that when A/UX Release 2.0 implements a particular manager or driver, the
- version of that manager or driver may not be the same as the version available
- in the Macintosh Operating System. This means that, whenever possible, you
- should use Gestalt to check for the existence of the particular features your
- application needs. In managers or drivers marked with an asterisk (*), all calls
- are implemented under A/UX, but the behavior is not identical to that in the
- Macintosh Operating System. See the publication A/UX Toolbox: Macintosh ROM
- Interface for complete details on the implementation of these managers and
- drivers.
-
- _______________________________________________________________________________
-
- æKY A/UX…Compatibility…Guidelines
- æC »A/UX Compatibility Guidelines Compatibility Guidelines
- _______________________________________________________________________________
-
- The A/UX Toolbox has been designed to allow as many Macintosh applications as
- possible to execute under the A/UX operating system. Because of profound
- differences between the two environments, however, it is possible that some
- applications may not execute correctly under A/UX. By following these
- guidelines, you can help ensure that your Macintosh applications run under A/UX.
-
- • Make certain that your application is MultiFinder-friendly. MultiFinder
- is a standard part of A/UX Release 2.0, just as it is in system software
- version 7.0. Your application should include a 'SIZE' resource and call
- WaitNextEvent in its main event loop. Note that the version of
- MultiFinder included with A/UX Release 2.0 is functionally equivalent to
- the version of MultiFinder released with system software version 6.0.5,
- but has been customized for use under A/UX.
-
- • Always use the available managers and drivers to manipulate hardware
- devices. In the Macintosh Operating System, individual processes and the
- various libraries can have much more control over the system than under
- A/UX, where the kernel manages all interaction between processes and the
- underlying hardware. In particular, do not attempt to read data from or
- write data to any of the memory-mapped hardware available on a Macintosh
- computer.
-
- • Avoid relying on any of the low-memory global variables. Not all of them
- are available under A/UX.
-
- • Make certain that your application is 32-bit clean (that is, it operates
- in an environment where all 32 bits of a handle or pointer are
- significant in determining memory addresses).
-
- • Use the Gestalt Manager to determine which versions of managers and
- drivers are present in the current operating environment before relying
- on features that are not common to all released versions. Generally, the
- versions of managers available under A/UX Release 2.0 are the same as
- those versions included in Macintosh system software version 6.0.5.
-
- Finally, your application should conform to the programming interfaces described
- in Inside Macintosh and should follow the basic compatibility guidelines
- presented in “About Compatibility” earlier in this chapter.
-
- _______________________________________________________________________________
-
- æKY About…the…Gestalt…Manager
- æC »ABOUT THE GESTALT MANAGER Compatibility Guidelines
- _______________________________________________________________________________
-
- The Macintosh family of computers has grown tremendously in the past several
- years, and it is likely to grow in the future. Macintosh software now runs on a
- number of different processors, some of which are accompanied by floating-point
- coprocessors or memory management units. In addition, the installed versions of
- the system software, drivers, and QuickDraw routines may vary from machine to
- machine. To ensure that your applications are maximally compatible with existing
- and future versions of the Macintosh, you should keep references to specific
- software and hardware features to a minimum. In general, applications should
- communicate with the system software and hardware through the available managers
- and device drivers. If, however, it is necessary or useful for your applications
- to take advantage of software or hardware components that may not be present on
- all Macintosh computers, then you need some method of determining whether those
- components are available. The Gestalt Manager serves this need by allowing you
- to get information about the operating environment in a simple and efficient
- manner.
-
- System software version 7.0 is a major software release that affects the entire
- Macintosh line of computers, spanning different CPUs, different versions of ROM,
- and machines with a variety of hardware and software configurations. Version 7.0
- introduces several new managers and makes significant changes to many existing
- managers. To take advantage of new version 7.0 features, and to run on as many
- machines as possible, it is more important than ever before to determine the
- software and hardware components available in a particular operating
- environment.
-
- To deal with this increasingly complex situation, system software version 7.0
- includes the Gestalt Manager. This manager includes the Gestalt function, which
- is a replacement for both the SysEnvirons function and the Environs procedure.
- The Gestalt function gives applications the ability to determine information
- about a large number of machine-dependent features. You can use the Gestalt
- function to find the following sorts of information about the hardware
- configuration and operating environment of the machine your application is
- executing on:
-
- • the type of machine
- • the version of the System file currently running
- • the type of CPU
- • the type of keyboard attached to the machine
- • the type of floating-point processing unit (FPU), if any
- • the type of memory management unit (MMU), if any
- • the size of available RAM
- • the amount of available virtual memory
- • the versions of various drivers and managers
- • the features of various drivers and managers
- • the version of QuickDraw currently present
- • whether the A/UX operating system is running or not
-
- How your application uses the resulting information depends on what your
- application needs to accomplish. For example, in a case where critical hardware
- features are not available, your application might display an alert box to
- notify the user that the required hardware is missing and then terminate. Or, if
- your application has determined that Color QuickDraw is available, it could
- execute alternate code to take advantage of the expanded capabilities of that
- software.
-
- Associated with the Gestalt function are two other functions—one that allows an
- application to register new features with Gestalt and another that allows an
- application to change the function used by Gestalt to retrieve a particular
- piece of information. These two functions make it easy for your application to
- announce its presence to other applications, in case they wish to alter their
- actions in view of the presence of your application. For example, a macro
- utility that intercepts sequences of keyboard presses and translates them into
- other sequences can register itself with Gestalt at system initialization time;
- afterward, other applications can call Gestalt to determine if that utility is
- present. In this way, Gestalt can act as a central clearinghouse for information
- on the available hardware and software features of the operating environment,
- including any third-party applications that register themselves with Gestalt.
- Gestalt therefore provides a further means of cooperation and awareness among
- applications executing in the version 7.0 environment.
-
- Although the Gestalt function can provide your application with most of the
- basic information it needs about particular software or hardware features, you
- may still need to call other routines to determine more specific features. For
- example, if you need to determine the resolution of the Macintosh screen, you
- can use the Toolbox Utility procedure ScreenRes. (See the Toolbox Utilities
- chapter of Inside Macintosh, Volume I, for a description of this procedure.)
- The Gestalt function replaces both the Environs procedure and the current
- implementation of the SysEnvirons function as the standard means of determining
- specific aspects of the operating environment. The Gestalt Manager is simpler to
- use and provides more information than either of those routines. Applications
- that use SysEnvirons still execute correctly in system software version 7.0 (the
- SysEnvirons function calls the Gestalt function).
-
- Use of the Environs procedure is no longer recommended, because it encourages
- you to think in terms of ROM versions, not in term of features that may be
- available. The Gestalt Manager can also provide information such as ROM version
- and size, but you should not write applications that infer the presence of
- particular software or hardware features on the basis of that information. When
- you need to know whether a particular feature is present, you should request
- information about it directly, using the appropriate Gestalt selector.
-
- Although you can still call the SysEnvirons function, the Gestalt Manager is
- simpler and more efficient, and is the recommended way to get information about
- the operating environment. SysEnvirons returns a pointer to a system environment
- record containing nine different pieces of information. Gestalt returns only the
- information requested by use of a specific selector code parameter. In most
- cases, your application really needs only a part of what is contained in the
- system environment record. With Gestalt, your application can request only the
- information it needs.
-
- _______________________________________________________________________________
-
- æKY Using…the…Gestalt…Manager
- æC »USING THE GESTALT MANAGER Compatibility Guidelines
- _______________________________________________________________________________
-
- The Gestalt Manager includes three functions—Gestalt, NewGestalt, and
- ReplaceGestalt. You can use the Gestalt function to obtain information about
- software or hardware components available on the current machine. You can use
- NewGestalt to register new software modules (such as drivers and patches) with
- the Operating System. Use ReplaceGestalt to replace the function associated with
- a particular selector code by some other function.
-
- Note: Most applications do not need to use either NewGestalt or ReplaceGestalt.
-
- _______________________________________________________________________________
-
- æKY Determining…Features…of…the…Operating…Environment
- æC »Determining Features of the Operating Environment Compatibility Guidelines
- _______________________________________________________________________________
-
- When your application needs information about a specific software or hardware
- feature that can be provided by the Gestalt function, your application can pass
- Gestalt a selector code (or selector) as one of the parameters. The selector
- code is simply an indication of what information your application currently
- needs. There are two types of selector codes—predefined selector codes that are
- always recognized by Gestalt, and application-defined selector codes that
- applications may register with Gestalt by calling the NewGestalt function.
-
- If Gestalt can determine the requested information, it returns that information
- in its second parameter, known as the response parameter. If Gestalt cannot
- obtain the desired information, it returns a result code indicating the cause of
- the error, and the value of the response parameter is undefined. You should
- always check the result code returned by Gestalt to make sure that the response
- parameter contains meaningful information.
-
- Note: When passed one of the predefined selector codes, Gestalt does not move
- or purge memory and therefore may be called at any time, even at interrupt time.
- However, selector functions associated with application-defined selector codes
- may move or purge memory, and applications can alter Gestalt’s predefined
- selector functions. As a result, it is safest to assume that Gestalt might
- always move or purge memory. The NewGestalt function may move memory and should
- not be called at interrupt time.
-
- There are two types of predefined selector codes: codes that return information
- that your application can use to guide its actions (known as environmental
- selectors), and codes that provide information only and should never be used as
- an indication of some feature’s existence (known as informational selectors).
-
- It is particularly important that you understand the difference between
- environmental and informational selectors. The response returned by Gestalt when
- it is passed an informational selector is for your (or the user’s) edification
- only and should never be used by your application as a means of determining
- whether some specific software or hardware feature is available. For example,
- you can use Gestalt to determine the version of the ROM installed on a
- particular machine, but you should never use this information to guide any of
- your application’s actions. Routines you expect to be in ROM may actually be in
- RAM; hence, you cannot determine that some routine usually found in ROM is not
- present simply by looking at the ROM version. Also, routines contained in ROM
- may have been patched by the system at startup time, in which case the system
- might not have the features that you think it has on the basis of the reported
- ROM version. Similar remarks apply to other informational selectors such as ROM
- size, machine type, and System file version.
-
- You can use the following environmental selectors to determine information about
- the operating environment.
-
- CONST
- gestaltVersion = 'vers'; {Gestalt version}
- gestaltAddressingModeAttr = 'addr'; {addressing mode attributes}
- gestaltAliasMgrAttr = 'alis'; {Alias Mgr attributes}
- gestaltAppleTalkVersion = 'atlk'; {AppleTalk version}
- gestaltAUXVersion = 'a/ux'; {A/UX version if present}
- gestaltCTBVersion = 'ctbv'; {Comm Toolbox version}
- gestaltDBAccessMgrAttr = 'dbac'; {Database Access Mgr attrs}
- gestaltEditionMgrAttr = 'edtn'; {Edition Mgr attributes}
- gestaltAppleEventsAttr = 'evnt'; {AppleEvents attributes}
- gestaltFolderMgrAttr = 'fold'; {Folder Mgr attributes}
- gestaltFontMgrAttr = 'font'; {Font Mgr attributes}
- gestaltFPUType = 'fpu '; {FPU type}
- gestaltHardwareAttr = 'hdwr'; {hardware attributes}
- gestaltHelpMgrAttr = 'help'; {Help Mgr attributes}
- gestaltKeyboardType = 'kbd '; {keyboard type}
- gestaltLowMemorySize = 'lmem'; {low-memory area size}
- gestaltLogicalRAMSize = 'lram'; {logical RAM size}
- gestaltMiscAttr = 'misc'; {miscellaneous attributes}
- gestaltMMUType = 'mmu '; {MMU type}
- gestaltNotificationMgrAttr = 'nmgr'; {Notification Mgr attrs}
- gestaltOSAttr = 'os '; {O/S attributes}
- gestaltLogicalPageSize = 'pgsz'; {logical page size}
- gestaltPPCToolboxAttr = 'ppc '; {PPC Toolbox attributes}
- gestaltPowerMgrAttr = 'powr'; {Power Mgr attributes}
- gestaltProcessorType = 'proc'; {processor type}
- gestaltParityAttr = 'prty'; {parity attributes}
- gestaltQuickdrawVersion = 'qd '; {QuickDraw version}
- gestaltPhysicalRAMSize = 'ram '; {physical RAM size}
- gestaltResourceMgrAttr = 'rsrc'; {Resource Mgr attributes}
- gestaltScriptMgrVersion = 'scri'; {Script Mgr version}
- gestaltScriptCount = 'scr#'; {# of active script systems}
- gestaltSoundAttr = 'snd '; {sound attributes}
- gestaltTextEditVersion = 'te '; {TextEdit version}
- gestaltTimeMgrVersion = 'tmgr'; {Time Mgr version}
- gestaltVMAttr = 'vm '; {virtual memory attributes}
-
- The following informational selectors are provided for informational purposes
- only. You can display the information returned when using these selectors, but
- you should never use this information as an indication of what software features
- or hardware may be available.
-
- CONST
- gestaltMachineType = 'mach'; {machine type}
- gestaltROMSize = 'rom '; {ROM size}
- gestaltROMVersion = 'romv'; {ROM version}
- gestaltSystemVersion = 'sysv'; {System file version}
-
- “Interpreting Gestalt Responses” later in this chapter provides the exact
- meaning of each of these selectors and of the values returned by Gestalt in each
- case.
-
- _______________________________________________________________________________
-
- æKY Determining…Whether…Gestalt…Is…Available
- æC »Determining Whether Gestalt Is Available Compatibility Guidelines
- _______________________________________________________________________________
-
- Because the Gestalt Manager currently exists only in system software versions
- 6.0.4 and later (and in ROM on the Macintosh IIci and Portable), you should make
- certain that it is actually available before attempting to call it. You can do
- this by using the TrapAvailable function defined above in “Determining Whether a
- Trap Is Available.” Listing 3-3 uses that function to determine whether the
- Gestalt Manager is available.
-
- Note: If you are using the MPW development system version 3.2 or later, then
- you do not need to perform this check, because that system provides glue
- routines that allow you to call Gestalt even if it is not in ROM or in the
- System file. However, if you are programming in assembly language, this glue is
- not provided (and you still need to check that Gestalt is available before
- calling it).
-
- Listing 3-3. Determining whether Gestalt is available
-
- FUNCTION GestaltAvailable: Boolean;
- CONST
- _Gestalt = $A1AD;
- BEGIN
- GestaltAvailable := TrapAvailable(_Gestalt);
- END;
-
- If you need to know at several different places in your application whether
- Gestalt is available, it may be more efficient to define a global Boolean
- variable that you can test before calling Gestalt. Listing 3-4 illustrates how
- to do this. Once again, this code uses the TrapAvailable function defined
- earlier.
-
- Listing 3-4. Using Gestalt to determine the Time Manager version
-
- VAR
- hasGestalt: Boolean; {true if Gestalt is implemented}
-
- hasGestalt := TrapAvailable(_Gestalt);
- .
- .
- .
-
- IF hasGestalt THEN BEGIN
- myErr := Gestalt(gestaltTimeMgrVersion, myFeature);
- IF myErr <> noErr THEN
- DoError(myErr);
- END;
-
- This sample code returns (in the myFeature variable) the version of the Time
- Manager available on the current machine. Before using that information,
- however, you should test the result code to make sure that Gestalt was able to
- determine the requested information.
-
- _______________________________________________________________________________
-
- æKY Interpreting…Gestalt…Responses
- æC »Interpreting Gestalt Responses Compatibility Guidelines
- _______________________________________________________________________________
-
- When your application calls Gestalt to get information about the operating
- environment, the meaning of the value that Gestalt returns in the response
- parameter depends on the selector code with which it was called. For example, a
- call to Gestalt using the gestaltTimeMgrVersion selector returns a version code
- in the low-order byte of the response parameter. In this case, a returned value
- of 3 indicates that the extended Time Manager is available.
-
- In almost all cases, the last few characters in the selector’s symbolic name
- form a suffix that indicates what type of value you can expect Gestalt to
- return. For example, if the final characters in a Gestalt selector are Addr,
- then Gestalt returns an address in the response parameter. The following list
- shows the meaningful suffixes.
-
- Suffix Meaning
-
- Addr The returned value is an address.
-
- Attr The returned value is a range of bits, the meaning of which must be
- determined by comparison with a list of constants. Note that bit 0 is
- the least significant bit of the long word.
-
- Count The returned value is a number indicating how many of the indicated type
- of item exist.
-
- Size The returned value is a size. Sizes reported by Gestalt are usually in
- bytes.
-
- Type The returned value is an index describing a particular type of feature.
-
- Version The returned value is a version number. Implied decimal points may
- separate digits of the returned value. For example, a value of $0603
- returned in response to the gestaltSystemVersion selector indicates
- that system software version 6.0.3 is present.
-
- Selectors that have the suffix Attr deserve special attention; they cause
- Gestalt to return a bit field that your application must interpret in order to
- determine whether a desired feature is present. For example, the gestaltOSAttr
- selector requests information about a number of Operating System features. To
- determine whether a particular Operating System feature is available, you need
- to read the appropriate bit in the response parameter, as Listing 3-5
- illustrates.
-
- Listing 3-5. Interpreting a bit field response
-
- VAR
- myBit: Integer;
- myFeature: LongInt;
- myErr: Integer;
-
- IF hasGestalt THEN BEGIN
- myErr := Gestalt(gestaltOSAttr, myFeature);
- IF myErr <> noErr THEN
- DoError(myErr)
- ELSE BEGIN
- myBit := gestaltTempMemSupport;
- IF BTst(myFeature, 31-myBit) = TRUE THEN
- WriteLn('temporary memory support available')
- ELSE
- WriteLn('temporary memory support not available');
- END;
- END;
-
- This code uses the MPW function BTst to determine if the appropriate bit in
- Gestalt’s response is equal to 1. Your development system may have other ways of
- testing the appropriate bit.
-
- _______________________________________________________________________________
-
- æKY Interpreting…Responses…to…Environmental…Selectors
- æC »Interpreting Responses to Environmental Selectors Compatibility Guidelines
- _______________________________________________________________________________
-
- Gestalt returns one of the following responses when passed a predefined
- environmental selector.
-
- gestaltVersion
-
- Returns the version of Gestalt. The current version is 1, corresponding to a
- returned value of $0001.
-
- gestaltAddressingModeAttr
-
- Returns information about the current addressing.
-
- CONST
- gestalt32BitAddressing = 0;
- gestalt32BitSysZone = 1;
- gestalt32BitCapable = 2;
-
- The gestalt32BitAddressing attribute indicates that the machine started up with
- 32-bit addressing. The gestalt32BitSysZone attribute indicates that the system
- heap has 32-bit clean block headers (regardless of the type of addressing the
- machine started up in). See the Memory Management chapter for more information
- about 32-bit addressing.
-
- gestaltAliasMgrAttr
-
- Returns information about the Alias Manager.
-
- CONST
- gestaltAliasMgrPresent = 0;
-
- gestaltAppleTalkVersion
-
- Returns the version number of the AppleTalk driver currently installed. In
- particular, it returns the version number of the MPP driver. The version number
- is placed into the low-order byte of the result, so you should ignore the three
- high-order bytes of the result. If an AppleTalk driver is not currently open,
- the response parameter is 0. The driver will not be opened until the user
- requests a network service (such as Chooser).
-
- gestaltAUXVersion
-
- Returns the version of A/UX if it is currently executing. The result is placed
- into the lower word of the response parameter. If A/UX is not executing, Gestalt
- returns gestaltUnknownErr.
-
- gestaltCTBVersion
-
- Returns the version number of the Communications Toolbox.
-
- gestaltDBAccessMgrAttr
-
- Returns information about the Database Access Manager.
-
- CONST
- gestaltDBAccessMgrPresent = 0;
-
- gestaltEditionMgrAttr
-
- Returns information about the Edition Manager.
-
- CONST
- gestaltEditionMgrPresent = 0;
-
- gestaltAppleEventsAttr
-
- Returns information about AppleEvents.
-
- CONST
- gestaltAppleEventsPresent = 0;
-
- gestaltFolderMgrAttr
-
- Returns information about the Folder Manager.
-
- CONST
- gestaltFolderMgrPresent = 0;
-
- gestaltFontMgrAttr
-
- Returns information about the Font Manager.
-
- CONST
- gestaltOutlineFonts = 0;
-
- gestaltFPUType
-
- Returns a value that indicates the type of floating-point coprocessor currently
- installed, if any.
-
- CONST
- gestaltNoFPU = 0;
- gestalt68881 = 1;
- gestalt68882 = 2;
-
- gestaltHardwareAttr
-
- Returns information about the hardware configuration of the machine.
-
- CONST
- gestaltHasVIA1 = 0;
- gestaltHasVIA2 = 1;
- gestaltHasASC = 3;
- gestaltHasSCC = 4;
- gestaltHasSCSI = 7;
-
- gestaltHelpMgrAttr
-
- Returns information about the Help Manager.
-
- CONST
- gestaltHelpMgrPresent = 0;
-
- gestaltKeyboardType
-
- Returns a value that indicates the type of keyboard that is currently attached
- to the system.
-
- CONST
- gestaltMacKbd = 1;
- gestaltMacAndPad = 2;
- gestaltMacPlusKbd = 3;
- gestaltExtADBKbd = 4;
- gestaltStdADBKbd = 5;
- gestaltPrtblADBKbd = 6;
- gestaltPrtblISOKbd = 7;
- gestaltStdISOADBKbd = 8;
- gestaltExtISOADBKbd = 9;
-
- If the Apple Desktop Bus™ is in use, there may be multiple keyboards or other
- ADB devices attached to the machine. Gestalt returns the type of the keyboard on
- which the last keystroke occurred.
-
- gestaltLowMemorySize
-
- Returns the size (in bytes) of the low-memory area. The low-memory area is used
- for vectors, global variables, and dispatch tables.
-
- gestaltLogicalRAMSize
-
- Returns the amount of logical memory available. This value is the same as that
- returned by gestaltPhysicalRAMSize when virtual memory is not installed. On some
- machines, however, this value might be less than the value returned by
- gestaltPhysicalRAMSize, because some RAM may be used by the video display and
- the Operating System.
-
- gestaltMiscAttr
-
- Returns information about miscellaneous pieces of the Operating System or
- hardware configuration. Currently only one value is returned.
-
- CONST
- gestaltScrollingThrottle = 0;
-
- gestaltMMUType
-
- Returns a value that indicates the type of MMU currently installed, if any.
-
- CONST
-
- gestaltNoMMU = 0;
- gestaltAMU = 1;
- gestalt68851 = 2;
- gestalt68030MMU = 3;
-
- gestaltNotificationMgrAttr
-
- Returns information about the Notification Manager.
-
- CONST
- gestaltNotificationMgrPresent = 0;
-
- gestaltOSAttr
-
- Returns general information about the Operating System, such as whether
- temporary memory handles are real handles. The low-order bits of the response
- parameter are interpreted as bit flags. A flag is set to 1 to indicate that the
- corresponding feature is available. Currently the following bits are
- significant:
-
- CONST
- gestaltSysZoneGrowable = 0;
- gestaltLaunchCanReturn = 1;
- gestaltLaunchFullFileSpec = 2;
- gestaltLaunchControl = 3;
- gestaltTempMemSupport = 4;
- gestaltRealTempMemory = 5;
- gestaltTempMemTracked = 6;
- gestaltIPCSupport = 7;
- gestaltSysDebuggerSupport = 8;
-
- See the Memory Management chapter in this volume for a full explanation of the
- temporary memory features and the Process Management chapter for a full
- explanation of the launch control features.
-
- gestaltLogicalPageSize
-
- Returns the logical page size. This value is an unknown on 68000-based machines,
- since such machines do not have logical pages. On those machines, Gestalt
- returns an error.
-
- gestaltPowerMgrAttr
-
- Returns information about the Power Manager, if present.
-
- CONST
- gestaltPMgrExists = 0;
- gestaltPMgrCPUIdle = 1;
- gestaltPMgrSCC = 2;
- gestaltPMgrSound = 3;
-
- gestaltPPCToolboxAttr
-
- Returns information about the capabilities of the PPC Toolbox.
-
- CONST
- gestaltPPCToolboxPresent = 0;
- gestaltPPCRealTime = 1;
-
- gestaltProcessorType
-
- Returns a value that indicates the type of processor that is currently running.
-
- CONST
- gestalt68000 = 1;
- gestalt68010 = 2;
- gestalt68020 = 3;
- gestalt68030 = 4;
-
- gestaltParityAttr
-
- Returns information about the parity-checking abilities of the machine.
-
- CONST
- gestaltHasParityCapability = 0;
- gestaltParityEnabled = 1;
-
- Note that parity is not considered to be enabled unless all installed memory is
- parity RAM.
-
- gestaltQuickdrawVersion
-
- Returns a 2-byte value indicating the version of QuickDraw currently present.
- The high-order byte of that number represents the major revision number, and the
- low-order byte represents the minor revision number. For example, the Macintosh
- IIci contains QuickDraw version 2.01 in ROM; on that machine, Gestalt returns
- the value $0201.
-
- CONST
- gestaltOriginalQD = $000;
- gestalt8BitQD = $100;
- gestalt32BitQD = $200;
-
- Values having a major revision number of 1 and 2 indicate that Color QuickDraw
- is available, in either the 8-bit or 32-bit version. These results do not,
- however, indicate whether a color monitor is attached to the system. You need to
- use high-level QuickDraw routines to obtain that information.
-
- gestaltPhysicalRAMSize
-
- Returns the number of bytes of physical RAM currently installed.
-
- gestaltResourceMgrAttr
-
- Returns information about the capabilities of the Resource Manager.
-
- CONST
- gestaltPartialRsrcsExist = 0;
- gestaltDecompression = 1;
-
- gestaltScriptMgrVersion
-
- Returns the version number of the Script Manager.
-
- gestaltScriptCount
-
- Returns the number of scripts currently active.
-
- gestaltSoundAttr
-
- Returns information about the sound capabilities of the machine.
-
- CONST
- gestaltStereoCapability = 0;
- gestaltStereoMixing = 1;
-
- The response gestaltStereoCapability indicates that the Sound Manager can play
- stereo sounds. The response gestaltStereoMixing indicates that the sound
- hardware of the machine mixes both left and right channels of stereo sound into
- a single audio signal for the internal speaker.
-
- gestaltTextEditVersion
-
- Returns a value that indicates which version of TextEdit is present.
-
- CONST
- gestaltTE1 = 1;
- gestaltTE2 = 2;
- gestaltTE3 = 3;
- gestaltTE4 = 4;
-
- See the TextEdit chapter in this volume for further information on the
- capabilities of these enhanced versions of TextEdit.
-
- gestaltTimeMgrVersion
-
- Returns a value that indicates the version of the Time Manager that is present.
-
- CONST
- gestaltStandardTimeMgr = 1;
- gestaltRevisedTimeMgr = 2;
- gestaltExtendedTimeMgr = 3;
-
- See the Time Manager chapter in this volume for a complete explanation of the
- capabilities of each of these three versions.
-
- gestaltVMAttr
-
- Returns information about virtual memory.
-
- CONST
- gestaltVMPresent = 1;
- _______________________________________________________________________________
-
- æKY Interpreting…Responses…to…Informational…Selectors
- æC »Interpreting Responses to Informational Selectors Compatibility Guidelines
- _______________________________________________________________________________
-
- Gestalt returns the following responses when passed a predefined informational
- selector.
-
- † Warning: Never infer the existence of certain hardware or software features
- from the responses that Gestalt returns to your application when you pass it
- these selectors.Ê
-
- gestaltMachineType
-
- Returns one of the following values, indicating the type of machine on which the
- application is currently running.
-
- CONST
- gestaltClassic = 1; {Macintosh 128K}
- gestaltMacXL = 2; {Macintosh XL}
- gestaltMac512KE = 3; {Macintosh 512KE }
- gestaltMacPlus = 4; {Macintosh Plus}
- gestaltMacSE = 5; {Macintosh SE}
- gestaltMacII = 6; {Macintosh II}
- gestaltMacIIx = 7; {Macintosh IIx}
- gestaltMacIIcx = 8; {Macintosh IIcx}
- gestaltMacSE030 = 9; {Macintosh SE/30}
- gestaltPortable = 10; {Macintosh Portable}
- gestaltMacIIci = 11; {Macintosh IIci}
-
- Note that the machine type does not indicate which version or size of ROM is
- installed. To determine that information, you should use the two selectors
- gestaltROMSize and gestaltROMVersion.
-
- gestaltROMSize
-
- Returns the size of the installed ROM. The value is returned in a word.
-
- gestaltROMVersion
-
- Returns the version number of the installed ROM.
-
- gestaltSystemVersion
-
- Returns the version number of the currently active System file. This number is
- represented as two byte-long numbers. For example, if your application is
- running in version 6.0.4, then Gestalt returns the value $0604. You should
- ignore the high-order word of the returned value.
-
- _______________________________________________________________________________
-
- æKY Adding…Gestalt…Selectors
- æC »Adding Gestalt Selectors Compatibility Guidelines
- _______________________________________________________________________________
-
- You can add a new selector code to those already understood by Gestalt by
- calling the NewGestalt function. The NewGestalt function requires two
- parameters. The first parameter is the new selector to be registered. The second
- parameter is the address of a selector function, a function that is to be
- executed by Gestalt when it needs to determine what value to pass back when it
- is called with the new selector code.
-
- The selector code is a four-character sequence of type OSType. For example,
- Carl’s Object-Oriented Linker might register itself using the selector code
- 'COOL'. If you have registered a creator string with Apple, you are strongly
- encouraged to use that sequence as your selector code.
-
- Note: Apple reserves for its own use all four-character sequences consisting
- solely of lowercase letters and nonalphabetic ASCII characters.
-
- The selector function whose address you specify when registering a new Gestalt
- selector code can be any function that resides in the system heap and whose
- calling syntax conforms to that defined in “Specifying Gestalt Selector
- Functions” later in this chapter. Listing 3-6 illustrates how to install a
- simple function into the system heap and pass its address to NewGestalt.
-
- Listing 3-6. Installing a selector function into the system heap
-
- PROGRAM NewGestaltSample;
- USES
- Memtypes, OSIntf, ToolIntf, {standard includes}
- PasLibIntf, {for standard I/O, etc.}
- GestaltEqu, {for Gestalt}
- Traps; {for trap numbers}
- CONST
- mySelector = 'COOL'; {Gestalt function selector}
- gstFuncRsrcType = 'GDEF'; {Gestalt function resource type}
- gstFuncRsrcID = 128; {Gestalt function resource ID}
- VAR
- gestaltErr: OSErr; {error returned by Gestalt}
- gstFuncHandle: Handle; {handle to Gestalt function}
- oldGestaltFunc: ProcPtr; {pointer to old function}
- BEGIN
- {first make sure that Gestalt is available}
- IF NOT TrapAvailable(_Gestalt) THEN
- BEGIN
- WriteLn('Gestalt is not implemented.');
- IEexit(1)
- END;
- {load Gestalt function resource into system heap}
- gstFuncHandle := GetResource(gstFuncRsrcType, gstFuncRsrcID);
- IF gstFuncHandle = NIL THEN
- BEGIN
- WriteLn('Could not load Gestalt function resource.');
- IEexit(1)
- END;
- {detach it from the resource map so it stays around}
- DetachResource(gstFuncHandle);
- {add the new selector; first assume that it doesn't already exist}
- gestaltErr := NewGestalt(mySelector, ProcPtr(gstFuncHandle^));
- IF gestaltErr <> noErr THEN
- BEGIN
- WriteLn('Could not add as a new selector.');
- {try to replace existing selector}
- gestaltErr := ReplaceGestalt(mySelector,
- ProcPtr(gstFuncHandle^), oldGestaltFunc);
- IF gestaltErr <> noErr THEN
- BEGIN
- WriteLn('Could not replace selector either.');
- IEexit(1);
- END
- END;
- WriteLn('Selector installed.');
- END.
-
- You can ensure that the new Gestalt selector function is installed into the
- system heap by defining it as a resource (in this case, of type 'GDEF') whose
- resource attributes are resSysHeap and resLocked (in other words, lock the
- resource into the system heap). Listing 3-7 shows the relevant lines from a
- Makefile.
-
- Listing 3-7. Makefile directives to create a 'GDEF' resource
-
- GestaltFunc.p.o ƒ GestaltFunc.p
- Pascal GestaltFunc.p
-
- NewGestaltSample ƒƒ GestaltFunc.p.o
- Link GestaltFunc.p.o -rn ∂
- -ra =resSysHeap,resLocked ∂
- -rt GDEF=128
- -o NewGestaltSample
-
- Listing 3-8 shows the actual function definition, contained in the file
- GestaltFunc.p.
-
- Listing 3-8. Defining a new Gestalt function
-
- UNIT GestaltFunc;
- INTERFACE
- USES
- GestaltEqu; {for Gestalt}
- CONST
- myResult = $87654321; {Gestalt function response}
- FUNCTION gestaltCool (gestaltSelector: OSType;
- VAR gestaltResponse: LongInt) : OSErr;
-
- IMPLEMENTATION
- FUNCTION gestaltCool;
- BEGIN
- gestaltResponse := myResult; {return our response}
- gestaltCool := noErr; {return no error}
- END;
- END.
-
- Because the new selector function resides in the system heap, Gestalt recognizes
- and responds to the new selector until the machines restarts, even if your
- application terminates before that time. As a result, you might want your
- selector function to determine whether your application is still running before
- returning a value to Gestalt. If your application has terminated, the selector
- function should return an error.
-
- Note that if you try to register a selector that has already been registered
- with Gestalt, an error results.
-
- _______________________________________________________________________________
-
- æKY Modifying…Gestalt…Selectors
- æC »Modifying Gestalt Selectors Compatibility Guidelines
- _______________________________________________________________________________
-
- You can use the ReplaceGestalt function to modify the function that Gestalt
- executes when passed a particular selector code. As with the function whose
- address is passed to NewGestalt, the new function must must reside in the system
- heap and have a calling syntax that conforms to that defined in “Specifying
- Gestalt Selector Functions” later in this chapter. Listing 3-6 illustrates how
- to replace a Gestalt selector function.
-
- To allow the new function to call the function previously associated with the
- selector in question, the ReplaceGestalt function returns the address of the
- previous function.
-
- If you attempt to redefine a selector that is not yet defined, an error is
- returned; in that case, the address of the previous function is undefined.
- Accordingly, you should always test the result code of ReplaceGestalt before
- calling Gestalt with the selector in question.
-
- Note: If you modify the function associated with a predefined Gestalt selector,
- do not use any bits in the response parameter that are not documented in this
- chapter. Apple reserves all undocumented bits in the response parameter returned
- by predefined Gestalt selectors.
- _______________________________________________________________________________
-
- æKY Specifying…Gestalt…Selector…Functions
- æC »Specifying Gestalt Selector Functions Compatibility Guidelines
- _______________________________________________________________________________
-
- When you call the NewGestalt and ReplaceGestalt functions, you need to supply
- the address of a selector function that is called when some application passes
- the specified new or replacement selector to Gestalt. This selector function
- should have the following syntax and must reside in the system heap.
-
- FUNCTION selectorFunction (selector: OSType; VAR response: LongInt) : OSErr;
-
- When you pass the new or replacement selector to Gestalt, Gestalt calls the
- specified selector function to determine the information that Gestalt should
- pass back to the calling software. Your function should place the result in the
- long integer pointed to by the response parameter and should return the result
- code that Gestalt will return. This function should be as simple as possible and
- cannot use global variables in the A5 world unless A5 is set up explicitly and
- then restored upon exit. (See the Memory Management chapter in this volume for
- an explanation of setting up and restoring the A5 world.) Other Gestalt
- functions may be called using Gestalt from within this function.
-
- _______________________________________________________________________________
-
- æKY Gestalt…Manager…Routines
- æC »GESTALT MANAGER ROUTINES Compatibility Guidelines
- _______________________________________________________________________________
-
- This section describes the three functions in the Gestalt Manager—Gestalt,
- NewGestalt, and ReplaceGestalt. They allow you, respectively, to determine what
- hardware and software features are present in the operating environment, to add
- new selectors to those understood by the Gestalt function, and to replace the
- functions associated with known selectors.
-
- _______________________________________________________________________________
-
- æKY Getting…Information…About…the…Operating…Environment
- æC »Getting Information About the Operating Environment Compatibility Guidelines
- _______________________________________________________________________________
-
- Use the Gestalt function to obtain information about the operating environment.
- The information you need is indicated by the selector parameter, which Gestalt
- must already recognize.
-
- FUNCTION Gestalt (selector: OSType; VAR response: LongInt) : OSErr;
-
- Trap macro _Gestalt
- On entry D0: selector code
- On exit A0: response
- D0: result code
-
- Upon successful completion of the function, the response parameter contains the
- information requested. Note that Gestalt returns the results from all function
- selectors in a long integer, occupying 4 bytes. In some cases, not all 4 bytes
- are needed to hold the returned information, in which case Gestalt places the
- information in the low-order bytes of the response parameter.
-
- Result codes
- noErr 0 No error
- gestaltUnknownErr –5550 Could not obtain the response
- gestaltUndefSelectorErr –5551 Undefined selector
- _______________________________________________________________________________
-
- æKY Adding…Selector…Codes
- æC »Adding Selector Codes Compatibility Guidelines
- _______________________________________________________________________________
-
- Use the NewGestalt function to add selector codes to those already recognized by
- Gestalt.
-
- FUNCTION NewGestalt (selector: OSType; selectorFunction: ProcPtr) : OSErr;
-
- Trap macro _NewGestalt
- On entry A0: address of new selector function
- D0: selector code
- On exit D0: result code
-
- NewGestalt takes as parameters the selector to be registered and the function
- that Gestalt calls when it receives this selector. The interface for the
- selectorFunction function is defined in “Specifying Gestalt Selector Functions”
- earlier in this chapter.
-
- Result codes
- noErr 0 No error
- memFullErr –108 Ran out of memory
- gestaltDupSelectorErr –5552 Selector already exists
- gestaltLocationErr –5553 Function not in system heap
- _______________________________________________________________________________
-
- æKY Modifying…Selector…Codes
- æC »Modifying Selector Codes Compatibility Guidelines
- _______________________________________________________________________________
-
- The ReplaceGestalt function allows an application to replace the function that
- is currently associated with a selector.
-
- FUNCTION ReplaceGestalt (selector: OSType; selectorFunction: ProcPtr;
- VA